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

[소프트웨어 접근성] 가상 키보드 만들기 8 - 가상 키보드 만들기

언제나휴일 2016. 5. 13. 17:15
반응형

[소프트웨어 접근성] 가상 키보드 만들기 8 - 가상 키보드 만들기



 윈도우즈 폼 응용 프로젝트를 추가한 후에 키보드 이벤트와 마우스 이벤트 처리를 위한 WrapNative 클래스를 추가하세요. 이 부분은 앞에서 설명한 부분이라 별도의 설명은 생략할게요. 아래의 소스 코드를 참고하세요.

 

using System;

using System.Runtime.InteropServices;

using System.Windows.Forms;

using System.Threading;

namespace DemoKeyEvent

{

    [Flags]

    public enum KeyFlag{   KE_DOWN = 0, KE__EXTENDEDKEY=1, KE_UP = 2  }

    static class WrapNative

    {

        static Mutex mu = new Mutex();

        const int IME_CMODE_NATIVE = 0x1;

        [DllImport("imm32.dll")]

        static extern int ImmGetContext(int hWnd);

        [DllImport("imm32.dll")]

        static extern int ImmReleaseContext(int hWnd, int hImc);

        [DllImport("imm32.dll")]

        static extern int ImmGetConversionStatus(int hImc, out int fdwConversion,

                                              out int fdwSentence);

        [DllImport("imm32.dll")]

        static extern bool ImmSetConversionStatus(IntPtr hIMC, int fdwConversion,

                                                int fdwSentence);

        public static bool IsNativeMode(int handle)

        {

            int hImc, dwConversion = 0, dwSentense = 0;

            hImc = ImmGetContext(handle);

            ImmGetConversionStatus(hImc, out dwConversion, out dwSentense);

            return (dwConversion & IME_CMODE_NATIVE) == 1;

        }

        [DllImport("user32.dll")]

        private static extern int GetKeyboardState(byte[] pbKeyState);

        [DllImport("User32.dll")]

        static extern void keybd_event(byte vk, byte scan, int flags, int extra);

        public static void KeyDown(Keys keycode)

        {

            mu.WaitOne();

            keybd_event((byte)keycode,0,(int)(KeyFlag.KE_DOWN|KeyFlag.KE__EXTENDEDKEY),0);           

            mu.ReleaseMutex();

        }

        public static void KeyUp(Keys keycode)

        {

            mu.WaitOne();

            keybd_event((byte)keycode, 0, (int)(KeyFlag.KE_UP|KeyFlag.KE__EXTENDEDKEY), 0);           

            mu.ReleaseMutex();

        }

        public static void KeyClick(Keys keycode,bool shift)

        {

            mu.WaitOne();

            if (shift)

            {

                keybd_event((byte)Keys.ShiftKey,0,

                            (int)(KeyFlag.KE_DOWN|KeyFlag.KE__EXTENDEDKEY),0);

                keybd_event((byte)keycode, 0,

                            (int)(KeyFlag.KE_DOWN | KeyFlag.KE__EXTENDEDKEY), 0);

                keybd_event((byte)keycode, 0,

                            (int)(KeyFlag.KE_UP | KeyFlag.KE__EXTENDEDKEY), 0);               

                keybd_event((byte)Keys.ShiftKey, 0,

                            (int)(KeyFlag.KE_UP | KeyFlag.KE__EXTENDEDKEY), 0);

            }

            else

            {

                keybd_event((byte)keycode, 0,

                             (int)(KeyFlag.KE_DOWN | KeyFlag.KE__EXTENDEDKEY), 0);

                keybd_event((byte)keycode, 0,

                             (int)(KeyFlag.KE_UP | KeyFlag.KE__EXTENDEDKEY), 0);

            }

            mu.ReleaseMutex();

        }

        public static bool IsPress(Keys keycode)

        {

            byte[] vks = new byte[256];

            GetKeyboardState(vks);

            return vks[(int)keycode] == 1;

        }

    }

}

[소스] WrapNative.cs

 

 이번 작업에서는 논리적인 처리외에도 키보드 인터페이스 부분이 있어서 과도한 중복 작업이 존재합니다. 먼저 폼의 자식 컨트롤을 배치하세요.

가상 키보드 폼의 자식 컨트롤 배치

[그림] 가상 키보드 폼의 자식 컨트롤 배치

 

 다음은 자식 컨트롤에 배치한 컨트롤 형식과 컨트롤 이름입니다. 그림에는 보이지 않지만 좌측 상단에 정보를 표시할 레이블(Label lb_text)을 하나 배치하세요.

Button btn_toggle_ime; /영 변환

Button btn_esc; Esc

Button btn_f1; F1

Button btn_f2; F2

Button btn_f3; F3

Button btn_f4; F4

Button btn_f5; F5

Button btn_f6; F6

Button btn_f7; F7

Button btn_f8; F8

Button btn_f9; F9

Button btn_f10; F10

Button btn_f11; F11

Button btn_f12; F12

Button btn_equal; =

Button btn_dash; -

Button btn_0; 0

Button btn_9; 9

Button btn_8; 8

Button btn_7; 7

Button btn_6; 6

Button btn_5; 5

Button btn_4; 4

Button btn_3; 3

Button btn_2; 2

Button btn_1; 1

Button btn_fpu; ` (ESC )

Button btn_bs; \

Button btn_barrow; <-

Button btn_enter; Enter

Button btn_postb; ]

Button btn_preb; [

Button btn_p; p

Button btn_o; o

Button btn_i; i

Button btn_u; u

Button btn_y; y

Button btn_t; t

Button btn_r; r

Button btn_e; e

Button btn_w; w

Button btn_q; q

Button btn_tab; Tab

Button btn_upper; '(Enter )

Button btn_semi; ;

Button btn_l; l

Button btn_k; k

Button btn_j; j

Button btn_h; h

Button btn_g; g

Button btn_f; f

Button btn_d; d

Button btn_s; s

Button btn_a; a

Button btn_caps; Caps

Button btn_slush; /

Button btn_dot; .

Button btn_comma; ,

Button btn_m; m

Button btn_n; n

Button btn_b; b

Button btn_v; v

Button btn_c; c

Button btn_x; x

Button btn_z; z

Button btn_shift; Shift

Button btn_space; Space

Button btn_alt; Alt

Button btn_ctrl; Ctrl

ListBox lbox_event;

CheckBox cb_cabs;

CheckBox cb_with_shift;

Label lb_text; (좌측 상단에 레이블을 배치하세요.)

 

 

 이제 폼의 코드를 작성합시다. 먼저 현재 쉬프트 키를 눌렀는지 확인할 수 있는 멤버 필드를 선언하세요.

bool is_press_shift;

 한글 모드인지 확인할 수 있는 멤버 필드를 선언하세요.

bool check;

 자동화 요소의 초점 변경 이벤트 개체를 기억할 멤버를 선언하세요.

AutomationFocusChangedEventHandler afceh;

 현재 초점을 소유한 자동화 요소 개체와 값 패턴의 개체를 기억할 멤버를 선언합니다.

AutomationElement target_ae;

ValuePattern target;

 한글 개체를 기억할 멤버도 선업합니다.

Hangul hangul;

 폼의 Load 이벤트 핸들러를 추가하세요.

private void MainForm_Load(object sender, EventArgs e)

{

 초점 변경 이벤트 핸들러를 생성하여 등록합니다.

    afceh = new AutomationFocusChangedEventHandler(FocusChanged);

    Automation.AddAutomationFocusChangedEventHandler(afceh);

}

 

private void FocusChanged(object sender, AutomationFocusChangedEventArgs e)

{

 초점이 바뀌었을 때 AutomationElement 클래스의 정적 멤버인 FocusedElement를 이용하여 초점을 소유한 자동화 요소 개체를 참조합니다.

    AutomationElement ae = AutomationElement.FocusedElement;

 만약 멤버 필드로 기억하고 있는 타겟 요소와 같으면 이벤트 처리기를 끝냅니다.

    if (ae == target_ae){    return;    }

 만약 초점을 소유한 개체의 프로세스 ID가 현재 프로세스 ID와 같을 때도 이벤트 처리기를 끝냅니다.

    if (ae.Current.ProcessId == Process.GetCurrentProcess().Id){    return;    }

 자동화 요소 개체가 활성화 상태인지 확인합니다.

    if (ae.Current.IsEnabled)

    {

 활성화 상태이면 Value 패턴인지 확인합니다.

        object obj;

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

        {

 Value 패턴이면 타겟을 설정합니다. 이 부분은 크로스 스레드 문제가 발생할 수 있으므로 별도의 메서드를 만들게요.

            SetTarget(ae, obj);

        }

 Value 패턴이 아니면 타겟 자동화 요소와 타겟 Value 패턴을 null로 설정합니다.

        else{    target_ae = null;    target = null;    }

    }

 활성화 상태가 아니면 타겟 자동화 요소와 타겟 Value 패턴을 null로 설정합니다.

     else{    target_ae = null;    target = null;    }

}

 

 SetTarget 메서드를 정의합시다. 이 부분에서는 크로스 스레드 문제가 발생할 수 있어서 이를 처리하기 위한 대리자를 정의합니다.

delegate void SetTargetDele(AutomationElement ae,object obj);

private void SetTarget(AutomationElement ae,object obj)

{

 수행하고 있는 스레드가 폼을 소유하는 스레드인지 확인합니다.

    if(this.InvokeRequired)

    {

 만약 폼을 소유하는 스레드가 아니면 Invoke 메서드를 호출하여 .NET 프레임워크를 통해 폼을 소유한 스레드가 SetTarget 메서드를 호출할 수 있게 합니다.

        this.Invoke(new SetTargetDele(SetTarget),new object[]{ae,obj});

    }

    else

    {

 전달받은 타겟을 Value 패턴으로 참조 연산합니다.

        target = obj as ValuePattern;

 타겟 자동화 개체도 설정합니다.

        target_ae = ae;

 새로운 타겟을 설정하였으니 해당 개체에 한글 처리를 위한 한글 개체를 생성합니다.

        hangul = new Hangul();

 타겟의 값을 가져와 한글 개체의 Text 속성에 설정합니다.

        hangul.Text = target.Current.Value;

 정보를 표시할 레이블의 Text 속성도 설정합니다.

        lb_text.Text = hangul.Text;

 래핑한 API 정적 클래스 WrapNative IsPress 메서드를 호출하여 CapsLock 버튼을 누른 상태인지 얻어와서 cb_cabs Checked 속성을 설정합니다.

        cb_cabs.Checked = WrapNative.IsPress(Keys.CapsLock);

 이에 따라 키보드 UI 부분을 설정합니다. 이 부분은 ButtonSet 메서드로 구현합시다.

        ButtonSet();

 이벤트 정보를 표시할 리스트 박스에 항목을 추가합니다.

        lbox_event.Items.Add(ae.Current.Name);

    }

}


 키보드 버튼 상태에 따라 키보드 UI를 설정하는 ButtonSet 메서드를 정의합시다. 이 부분은 특별한 연산은 없지만 많은 키의 Text 속성을 설정하므로 작업량이 많습니다.

private void ButtonSet()

{

    if (is_press_shift)

    {

 쉬프트 키를 눌렀을 때 버튼의 Text 속성을 설정합시다.

        btn_fpu.Text = "~";  btn_1.Text = "!";       btn_2.Text = "@";

        btn_3.Text = "#";     btn_4.Text = "$";      btn_5.Text = "%";

        btn_6.Text = "^";     btn_7.Text = "&&";   btn_8.Text = "*";

        btn_9.Text = "(";      btn_0.Text = ")";       btn_dash.Text = "_";

        btn_equal.Text = "+";  btn_bs.Text = "|";    btn_preb.Text = "{";

        btn_postb.Text = "}"; btn_semi.Text = ":"; btn_upper.Text = "\"";

        btn_comma.Text = "<"; btn_dot.Text = ">"; btn_slush.Text = "?";

    }

    else

    {

 쉬프트 키를 누르지 않을 때의 버튼 Text 속성을 설정합시다.

        btn_fpu.Text = "`"; btn_1.Text = "1"; btn_2.Text = "2";

        btn_3.Text = "3";  btn_4.Text = "4";  btn_5.Text = "5";

        btn_6.Text = "6";  btn_7.Text = "7";  btn_8.Text = "8";

        btn_9.Text = "9";  btn_0.Text = "0";  btn_dash.Text = "-";

        btn_equal.Text = "=";   btn_bs.Text = "\\";

        btn_preb.Text = "[";  btn_postb.Text = "]";

        btn_semi.Text = ";";  btn_upper.Text = "'";

        btn_comma.Text = ","; btn_dot.Text = ".";

        btn_slush.Text = "/";

    }

 한글 모드인지 여부에 따라서 키보드 UI를 설정하는 부분도 필요합니다.

    if (check)

    {

        if (is_press_shift)

        {

 한글 모드에서 쉬프트 키를 눌렀을 때의 버튼 Text 속성을 설정하세요.

            btn_q.Text = ""; btn_w.Text = ""; btn_e.Text = "";

            btn_r.Text = "";  btn_t.Text = "";  btn_o.Text = "";

            btn_p.Text = "";

        }

 

        else

        {

 한글 모드에서 쉬프트 키를 누르지 않았을 때의 버튼 Text 속성을 설정하세요.

            btn_q.Text = ""; btn_w.Text = ""; btn_e.Text = "";

            btn_r.Text = "";  btn_t.Text = "";  btn_o.Text = "";

            btn_p.Text = "";

        }

 한글 모드에서 쉬프트 키에 관계없는 버튼의 Text 속성을 설정하세요.

        btn_y.Text = ""; btn_u.Text = ""; btn_i.Text = "";

        btn_a.Text = ""; btn_s.Text = ""; btn_d.Text = "";

        btn_f.Text = ""; btn_g.Text = ""; btn_h.Text = "";

        btn_j.Text = ""; btn_k.Text = ""; btn_l.Text = "";

        btn_z.Text = ""; btn_x.Text = ""; btn_c.Text = "";

        btn_v.Text = ""; btn_b.Text = ""; btn_n.Text = "";

        btn_m.Text = "";

    }

    else

    {

 한글 모드가 아닐 때의 처리입니다.

        if (is_press_shift ^ cb_cabs.Checked)

        {

쉬프트 키를 눌렀거나 CapsLock이 눌렀거나 둘 중에 하나가 참일 때의 처리입니다.

            btn_q.Text = "Q"; btn_w.Text = "W"; btn_e.Text = "E";

            btn_r.Text = "R";  btn_t.Text = "T";   btn_y.Text = "Y";

            btn_u.Text = "U"; btn_i.Text = "I";    btn_o.Text = "O";

            btn_p.Text = "P"; btn_a.Text = "A";  btn_s.Text = "S";

            btn_d.Text = "D"; btn_f.Text = "F";   btn_g.Text = "G";

            btn_h.Text = "H"; btn_j.Text = "J";    btn_k.Text = "K";

            btn_l.Text = "L";   btn_z.Text = "Z";  btn_x.Text = "X";

            btn_c.Text = "C"; btn_v.Text = "V";  btn_b.Text = "B";

            btn_n.Text = "N"; btn_m.Text = "M";

        }

        else

        {

 쉬프트 키를 누르고 CapsLock도 눌러진 상태이거나 둘 다 누른 상태가 아닐 때의 처리입니다.

            btn_q.Text = "q"; btn_w.Text = "w"; btn_e.Text = "e";

            btn_r.Text = "r"; btn_t.Text = "t"; btn_y.Text = "y";

            btn_u.Text = "u"; btn_i.Text = "i"; btn_o.Text = "o";

            btn_p.Text = "p"; btn_a.Text = "a"; btn_s.Text = "s";

            btn_d.Text = "d"; btn_f.Text = "f"; btn_g.Text = "g";

            btn_h.Text = "h"; btn_j.Text = "j"; btn_k.Text = "k";

            btn_l.Text = "l"; btn_z.Text = "z"; btn_x.Text = "x";

            btn_c.Text = "c"; btn_v.Text = "v"; btn_b.Text = "b";

            btn_n.Text = "n"; btn_m.Text = "m";

        }

    }

}

 

 cb_cabs 체크 박스의 체크 상태 변경 이벤트 핸들러를 등록하세요.

private void cb_cabs_CheckedChanged(object sender, EventArgs e)

{

 체크 상태에 따라 체크 박스의 배경 색을 다르게 지정하여 쉽게 알 수 있게 합시다.

    if (cb_cabs.Checked){    cb_cabs.BackColor = Color.YellowGreen;    }

    else{    cb_cabs.BackColor = SystemColors.Control;    }

}

 cb_with_shift 체크 박스의 체크 상태 변경 이벤트 핸들러를 등록하세요.

private void cb_with_shift_CheckedChanged(object sender, EventArgs e)

{

 is_press_shift에 현재 체크 상태로 설정하고 키보드 버튼의 UI 정보를 설정합니다.

    is_press_shift = cb_with_shift.Checked;

    ButtonSet();

}

 폼의 FormClosed 이벤트 핸들러를 등록합니다.

private void MainForm_FormClosed(object sender, FormClosedEventArgs e)

{

  Load할 때 등록했던 초점 변경 이벤트 핸들러를 해제합니다.

    Automation.RemoveAutomationFocusChangedEventHandler(afceh);

}


 모든 버튼의 클릭 이벤트는 Button_Click으로 추가하세요.

private void Button_Click(object sender, EventArgs e)

{

 

 먼저 어느 버튼인지 sender Button 형식으로 참조합니다.

    Button btn = sender as Button;

 만약 값 패턴 개체인 target이 존재하는지 확인합니다.

    if (target != null)

    {

 target이 존재하면 타겟에 초점을 설정합니다.

        target_ae.SetFocus();

 내부 처리 속도로 SetFocus를 호출해도 바로 초점을 잡지 않아 약간의 시간을 지연합니다.

        Thread.Sleep(10);

    }

 이제 버튼에 따라 처리를 합니다.

    switch (btn.Text)

    {

 다음은 래핑한 API 정적 클래스인 WrapNative KeyClick 메서드를 호출하여 프로그램 방식으로 키 이벤트를 발생할 키에 관한 처리입니다.

        case "Esc": WrapNative.KeyClick(Keys.Escape, is_press_shift); break;

        case "F1": WrapNative.KeyClick(Keys.F1, is_press_shift); break;

        case "F2": WrapNative.KeyClick(Keys.F2, is_press_shift); break;

        case "F3": WrapNative.KeyClick(Keys.F3, is_press_shift); break;

        case "F4": WrapNative.KeyClick(Keys.F4, is_press_shift); break;

        case "F5": WrapNative.KeyClick(Keys.F5, is_press_shift); break;

        case "F6": WrapNative.KeyClick(Keys.F6, is_press_shift); break;

        case "F7": WrapNative.KeyClick(Keys.F7, is_press_shift); break;

        case "F8": WrapNative.KeyClick(Keys.F8, is_press_shift); break;

        case "F9": WrapNative.KeyClick(Keys.F9, is_press_shift); break;

        case "F10": WrapNative.KeyClick(Keys.F10, is_press_shift); break;

        case "F11": WrapNative.KeyClick(Keys.F11, is_press_shift); break;

        case "F12": WrapNative.KeyClick(Keys.F12, is_press_shift); break;               

        case "Tab": WrapNative.KeyClick(Keys.Tab, is_press_shift); break;

        case "Shift": WrapNative.KeyClick(Keys.ShiftKey, is_press_shift); break;

        case "Enter": WrapNative.KeyClick(Keys.Enter, is_press_shift); break;

        case "Caps": WrapNative.KeyClick(Keys.CapsLock, is_press_shift);

 캡션 키를 눌렀을 때는 체크 박스의 체크 상태를 토글합니다.

            cb_cabs.Checked ^= true;

 캡션에 따라 키보드 UI 인터페이스의 내용이 바뀌어야 하므로 ButtonSet 메서드를 호출합니다.

            ButtonSet();    break;

        case "Ctrl": WrapNative.KeyClick(Keys.ControlKey, is_press_shift); break;

        case "Alt": WrapNative.KeyClick(Keys.Alt, is_press_shift); break;               

        case "/영 변환":

 /영 변환 버튼을 눌렀을 때도 한글 모드를 기억하는 check 멤버를 토클합니다.

            check ^= true;

 그리고 키보드 UI 인터페이스의 내용을 바꾸어야 하므로 ButtonSet 메서드를 호출합니다.

            ButtonSet();     break;

 Space 버튼을 누렀을 때는 별도의 메서드를 통해 문자를 누른 것처럼 처리할 PressKey 메서드를 이용하여 처리할게요.

         case "Space": PressKey(' '); break;

 <- 버튼을 눌렀을 때도 PressKey 메서드를 호출합시다.

         case "<-": PressKey('\b'); break;

 나머지 키는 버튼의 Text 속성의 첫번째 문자를 인자로 PressKey 메서드를 호출합니다.

        default: PressKey(btn.Text[0]); break;

    }

 키보드 이벤트를 보여줄 리스트 박스에 항목을 추가합니다.

    lbox_event.Items.Add(btn.Text);

 그리고 추가한 항목을 화면에 보일 수 있게 선택 항목으로 설정합니다.

    lbox_event.SelectedIndex = lbox_event.Items.Count - 1;

 래핑한 API 정적 클래스 WrapNative KeyClick 메서드를 이용해 End 키를 누른 이벤트를 발생합니다. 이를 통해 캐럿이 맨 뒤로 이동합니다.

    WrapNative.KeyClick(Keys.End,is_press_shift);

}


private void PressKey(char ch)

{

 만약 타겟 개체가 없으면 메서드를 종료합니다.

    if (target == null){    return;    }

 만약 한글 모드이면 hangul 개체의 Input 메서드를 호출합니다.

    if (check){    hangul.Input(ch);    }

 그렇지 않다면 한글 개체의 InputNoKorea 메서드를 호출합니다.

    else{    hangul.InputNoKorea(ch);    }

 정보를 표시할 레이블의 Text 속성을 한글의 Text 속성으로 설정합니다.

    lb_text.Text = hangul.Text;

 Value 패턴인 타겟의 SetValue 메서드를 이용하여 한글의 Text 속성으로 설정합니다.

    target.SetValue(hangul.Text);

}

using System;

using System.Drawing;

using System.Windows.Forms;

using System.Threading;

using EHHangulLibrary;

using System.Windows.Automation;

using System.Collections.Generic;

using System.Diagnostics;

 

namespace DemoKeyEvent

{

    public partial class Form1 : Form

    {

        bool is_press_shift;

        bool check;

 

        AutomationFocusChangedEventHandler afceh;

        AutomationElement target_ae;

        ValuePattern target;

        Hangul hangul;

       

        public Form1()

        {

            InitializeComponent();

        }

        private void MainForm_Load(object sender, EventArgs e)

        {

            afceh = new AutomationFocusChangedEventHandler(FocusChanged);

            Automation.AddAutomationFocusChangedEventHandler(afceh);

        }

        private void FocusChanged(object sender, AutomationFocusChangedEventArgs e)

        {

            AutomationElement ae = AutomationElement.FocusedElement;

            if (ae == target_ae){    return;    }

            if (ae.Current.ProcessId == Process.GetCurrentProcess().Id)

            {

                return;

            }

            if (ae.Current.IsEnabled)

            {

                object obj;

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

                {

                    SetTarget(ae, obj);

                }

                else

                {

                    target_ae = null;

                    target = null;

                }

            }

            else

            {

                target_ae = null;

                target = null;

            }

        }

        delegate void SetTargetDele(AutomationElement ae, object obj);

        private void SetTarget(AutomationElement ae, object obj)

        {

            if (this.InvokeRequired)

            {

                this.Invoke(new SetTargetDele(SetTarget), new object[] { ae, obj });

            }

            else

            {

                target = obj as ValuePattern;

                target_ae = ae;

                hangul = new Hangul();

                hangul.Text = target.Current.Value;

                lb_text.Text = hangul.Text;

                cb_cabs.Checked = WrapNative.IsPress(Keys.CapsLock);

                ButtonSet();

                lbox_event.Items.Add(ae.Current.Name);

            }

        }

        private void ButtonSet()

        {

            if (is_press_shift)

            {

                btn_fpu.Text = "~"; btn_1.Text = "!"; btn_2.Text = "@";

                btn_3.Text = "#"; btn_4.Text = "$"; btn_5.Text = "%";

                btn_6.Text = "^"; btn_7.Text = "&&"; btn_8.Text = "*";

                btn_9.Text = "("; btn_0.Text = ")"; btn_dash.Text = "_";

                btn_equal.Text = "+"; btn_bs.Text = "|"; btn_preb.Text = "{";

                btn_postb.Text = "}"; btn_semi.Text = ":"; btn_upper.Text = "\"";

                btn_comma.Text = "<"; btn_dot.Text = ">"; btn_slush.Text = "?";

            }

            else

            {

                btn_fpu.Text = "`"; btn_1.Text = "1"; btn_2.Text = "2";

                btn_3.Text = "3"; btn_4.Text = "4"; btn_5.Text = "5";

                btn_6.Text = "6"; btn_7.Text = "7"; btn_8.Text = "8";

                btn_9.Text = "9"; btn_0.Text = "0"; btn_dash.Text = "-";

                btn_equal.Text = "="; btn_bs.Text = "\\";

                btn_preb.Text = "["; btn_postb.Text = "]";

                btn_semi.Text = ";"; btn_upper.Text = "'";

                btn_comma.Text = ","; btn_dot.Text = ".";

                btn_slush.Text = "/";

            }

            if (check)

            {

                if (is_press_shift)

                {

                    btn_q.Text = ""; btn_w.Text = ""; btn_e.Text = "";

                    btn_r.Text = ""; btn_t.Text = ""; btn_o.Text = "";

                    btn_p.Text = "";

                }

                else

                {

                    btn_q.Text = ""; btn_w.Text = ""; btn_e.Text = "";

                    btn_r.Text = ""; btn_t.Text = ""; btn_o.Text = "";

                    btn_p.Text = "";

                }

                btn_y.Text = ""; btn_u.Text = ""; btn_i.Text = "";

                btn_a.Text = ""; btn_s.Text = ""; btn_d.Text = "";

                btn_f.Text = ""; btn_g.Text = ""; btn_h.Text = "";

                btn_j.Text = ""; btn_k.Text = ""; btn_l.Text = "";

                btn_z.Text = ""; btn_x.Text = ""; btn_c.Text = "";

                btn_v.Text = ""; btn_b.Text = ""; btn_n.Text = "";

                btn_m.Text = "";

            }

            else

            {

                if (is_press_shift ^ cb_cabs.Checked)

                {

                    btn_q.Text = "Q"; btn_w.Text = "W"; btn_e.Text = "E";

                    btn_r.Text = "R"; btn_t.Text = "T"; btn_y.Text = "Y";

                    btn_u.Text = "U"; btn_i.Text = "I"; btn_o.Text = "O";

                    btn_p.Text = "P"; btn_a.Text = "A"; btn_s.Text = "S";

                    btn_d.Text = "D"; btn_f.Text = "F"; btn_g.Text = "G";

                    btn_h.Text = "H"; btn_j.Text = "J"; btn_k.Text = "K";

                    btn_l.Text = "L"; btn_z.Text = "Z"; btn_x.Text = "X";

                    btn_c.Text = "C"; btn_v.Text = "V"; btn_b.Text = "B";

                    btn_n.Text = "N"; btn_m.Text = "M";

                }

                else

                {

                    btn_q.Text = "q"; btn_w.Text = "w"; btn_e.Text = "e";

                    btn_r.Text = "r"; btn_t.Text = "t"; btn_y.Text = "y";

                    btn_u.Text = "u"; btn_i.Text = "i"; btn_o.Text = "o";

                    btn_p.Text = "p"; btn_a.Text = "a"; btn_s.Text = "s";

                    btn_d.Text = "d"; btn_f.Text = "f"; btn_g.Text = "g";

                    btn_h.Text = "h"; btn_j.Text = "j"; btn_k.Text = "k";

                    btn_l.Text = "l"; btn_z.Text = "z"; btn_x.Text = "x";

                    btn_c.Text = "c"; btn_v.Text = "v"; btn_b.Text = "b";

                    btn_n.Text = "n"; btn_m.Text = "m";

                }

            }

        }

 

 

        private void cb_cabs_CheckedChanged(object sender, EventArgs e)

        {

            if (cb_cabs.Checked)

            {

                cb_cabs.BackColor = Color.YellowGreen;

            }

            else

            {

                cb_cabs.BackColor = SystemColors.Control;

            }

        }

        private void cb_with_shift_CheckedChanged(object sender, EventArgs e)

        {

            is_press_shift = cb_with_shift.Checked;

            ButtonSet();

        }

        private void MainForm_FormClosed(object sender, FormClosedEventArgs e)

        {

            Automation.RemoveAutomationFocusChangedEventHandler(afceh);

        }

        private void Button_Click(object sender, EventArgs e)

        {           

            Button btn = sender as Button;

            if (target != null)

            {

                target_ae.SetFocus();

                Thread.Sleep(10);

            }

            switch (btn.Text)

            {

                case "Esc": WrapNative.KeyClick(Keys.Escape, is_press_shift); break;

                case "F1": WrapNative.KeyClick(Keys.F1, is_press_shift); break;

                case "F2": WrapNative.KeyClick(Keys.F2, is_press_shift); break;

                case "F3": WrapNative.KeyClick(Keys.F3, is_press_shift); break;

                case "F4": WrapNative.KeyClick(Keys.F4, is_press_shift); break;

                case "F5": WrapNative.KeyClick(Keys.F5, is_press_shift); break;

                case "F6": WrapNative.KeyClick(Keys.F6, is_press_shift); break;

                case "F7": WrapNative.KeyClick(Keys.F7, is_press_shift); break;

                case "F8": WrapNative.KeyClick(Keys.F8, is_press_shift); break;

                case "F9": WrapNative.KeyClick(Keys.F9, is_press_shift); break;

                case "F10": WrapNative.KeyClick(Keys.F10, is_press_shift); break;

                case "F11": WrapNative.KeyClick(Keys.F11, is_press_shift); break;

                case "F12": WrapNative.KeyClick(Keys.F12, is_press_shift); break;               

                case "Tab": WrapNative.KeyClick(Keys.Tab, is_press_shift); break;               

                case "Shift": WrapNative.KeyClick(Keys.ShiftKey, is_press_shift); break;

                case "Enter": WrapNative.KeyClick(Keys.Enter, is_press_shift); break;

                case "Caps": WrapNative.KeyClick(Keys.CapsLock, is_press_shift);

                    cb_cabs.Checked ^= true;

                    ButtonSet();    break;

                case "Ctrl": WrapNative.KeyClick(Keys.ControlKey, is_press_shift); break;

                case "Alt": WrapNative.KeyClick(Keys.Alt, is_press_shift); break;               

                case "/영 변환":  check ^= true;    ButtonSet();        break;               

                case "Space": PressKey(' '); break;

                case "<-": PressKey('\b'); break;

                default: PressKey(btn.Text[0]); break;

            }

            lbox_event.Items.Add(btn.Text);

            lbox_event.SelectedIndex = lbox_event.Items.Count - 1;

            WrapNative.KeyClick(Keys.End,is_press_shift);

        }

        private void PressKey(char ch)

        {

            if (target == null){    return;    }

            if (check){    hangul.Input(ch);    }

            else

            {

                hangul.InputNoKorea(ch);

            }

            lb_text.Text = hangul.Text;

            target.SetValue(hangul.Text);           

        }

    }

}


반응형