윈도우즈 폼 응용 프로젝트를 추가한 후에 키보드 이벤트와 마우스 이벤트 처리를 위한 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; } } }
[소스 8.11] 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); } } }
[소스 8.12] Form1.cs