C#전역 키보드 스니핑(Hook) 사용

하나.글로벌 키보드 스니핑이 필요한 이유는 무엇입니까?
어떤 상황에서 응용 프로그램은 단축키가 특정한 기능을 수행해야 한다. 예를 들어 모두가 알고 있는 QQ 캡처 기능인 Ctrl+Alt+A 단축키는 QQ 프로그램이 실행 중이면(초점이 있든 백엔드가 실행 중이든) 단축키를 눌러서 사용할 수 있다.
이때 프로그램에 키보드 감청을 추가하면 수요를 충족시키지 못할 것이다. 사용자가 앱에 초점을 맞추지 않을 때(예를 들어 최소화하거나 사용자가 다른 사물을 처리하는 등) 키보드 감청은 효력을 상실한다.
둘.어떻게 해야만 전역 키보드 감청을 실현할 수 있습니까?
Windows API를 사용하려면 다음과 같은 소스가 필요합니다. (도구 클래스 [KeyboardHook.cs]로 저장할 수 있습니다.)using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; using System.Windows.Forms; using System.Reflection; namespace { /// /// /// [ , ] /// class KeyboardHook { public event KeyEventHandler KeyDownEvent; public event KeyPressEventHandler KeyPressEvent; public event KeyEventHandler KeyUpEvent; public delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam); static int hKeyboardHook = 0; // // Microsoft SDK Winuser.h // http://www.bianceng.cn/Programming/csharp/201410/45484.htm public const int WH_KEYBOARD_LL = 13; // 2, 13 HookProc KeyboardHookProcedure; // KeyboardHookProcedure HookProc // [StructLayout(LayoutKind.Sequential)] public class KeyboardHookStruct { public int vkCode; // 。 1 254 public int scanCode; // public int flags; // public int time; // public int dwExtraInfo; // } // , [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId); // [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] public static extern bool UnhookWindowsHookEx(int idHook); // , [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] public static extern int CallNextHookEx(int idHook, int nCode, Int32 wParam, IntPtr lParam); // ( ) [DllImport("kernel32.dll")] static extern int GetCurrentThreadId(); // WINDOWS API , [DllImport("kernel32.dll")] public static extern IntPtr GetModuleHandle(string name); public void Start() { // if (hKeyboardHook == 0) { KeyboardHookProcedure = new HookProc(KeyboardHookProc); hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHookProcedure, GetModuleHandle(System.Diagnostics.Process.GetCurrentProcess().MainModule.ModuleName), 0); //hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHookProcedure, Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]), 0); //************************************ // //SetWindowsHookEx( 2,KeyboardHookProcedure, IntPtr.Zero, GetCurrentThreadId());// idGetCurrentThreadId(), // , (using System.Reflection;) //SetWindowsHookEx( 13,MouseHookProcedure,Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]),0); // // SetWindowsHookEx (int idHook, HookProc lpfn, IntPtr hInstance, int threadId) , : //idHook , , 2, , 13, // 7, 14。lpfn 。 dwThreadId 0 // ,lpfn DLL 。 ,lpfn 。 , // 。hInstance 。 lpfn DLL。 threadId , // ,hInstance NULL。 。threaded // 0, , //************************************ // SetWindowsHookEx if (hKeyboardHook == 0) { Stop(); throw new Exception(" "); } } } public void Stop() { bool retKeyboard = true; if (hKeyboardHook != 0) { retKeyboard = UnhookWindowsHookEx(hKeyboardHook); hKeyboardHook = 0; } if (!(retKeyboard)) throw new Exception(" !"); } //ToAscii [DllImport("user32")] public static extern int ToAscii(int uVirtKey, //[in] 。 int uScanCode, // [in] 。 , ( ) byte[] lpbKeyState, // [in] , 256 , 。 ( ) 。 , ( )。 , , 。 , CAPS LOCK 。 NUM 。 byte[] lpwTransKey, // [out] 。 int fuState); // [in] Specifies whether a menu is active. This parameter must be 1 if a menu is active, or 0 otherwise. // [DllImport("user32")] public static extern int GetKeyboardState(byte[] pbKeyState); [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern short GetKeyState(int vKey); private const int WM_KEYDOWN = 0x100;//KEYDOWN private const int WM_KEYUP = 0x101;//KEYUP private const int WM_SYSKEYDOWN = 0x104;//SYSKEYDOWN private const int WM_SYSKEYUP = 0x105;//SYSKEYUP private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam) { // if ((nCode >= 0) && (KeyDownEvent != null || KeyUpEvent != null || KeyPressEvent != null)) { KeyboardHookStruct MyKeyboardHookStruct = (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct)); // raise KeyDown if (KeyDownEvent != null && (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN)) { Keys keyData = (Keys)MyKeyboardHookStruct.vkCode; KeyEventArgs e = new KeyEventArgs(keyData); KeyDownEvent(this, e); } // if (KeyPressEvent != null && wParam == WM_KEYDOWN) { byte[] keyState = new byte[256]; GetKeyboardState(keyState); byte[] inBuffer = new byte[2]; if (ToAscii(MyKeyboardHookStruct.vkCode, MyKeyboardHookStruct.scanCode, keyState, inBuffer, MyKeyboardHookStruct.flags) == 1) { KeyPressEventArgs e = new KeyPressEventArgs((char)inBuffer[0]); KeyPressEvent(this, e); } } // if (KeyUpEvent != null && (wParam == WM_KEYUP || wParam == WM_SYSKEYUP)) { Keys keyData = (Keys)MyKeyboardHookStruct.vkCode; KeyEventArgs e = new KeyEventArgs(keyData); KeyUpEvent(this, e); } } // 1, , , 。 // 0 CallNextHookEx , return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam); } ~KeyboardHook() { Stop(); } } }
셋.위의 도구류를 어떻게 사용합니까?
//0.준비 작업//위의 도구 클래스를 프로젝트에 추가
//1.먼저 필요한 네임스페이스 using System을 가져옵니다.Runtime.InteropServices;//WINDOWS API 함수를 호출할 때 using Microsoft를 사용합니다.Win32;//레지스트리에 쓸 때
//2.훅을 설치하고 프로그램 입구에 아래 코드를 적으세요(본 예에서 WinForm을 사용했고Form의 구조 방법에 훅을 설치하면 됩니다)//키보드 갈고리k 설치hook = new KeyboardHook(); k_hook.KeyDownEvent += new KeyEventHandler(hook_KeyDown);//훅 키 누르기 khook.Start();//키보드 갈고리를 설치하다
//3.키 값 입력(KeyDown 이벤트 구현) private void hook 판단KeyDown(object sender, Key EventArgse) {//누르는 키를 판단하기(Alt + A)if(e.Key Value = (int) Keys.A & & & (int) Control.Modifier Keys = (int) Keys.Alt) {System.Windows.Forms.MessageBox.Show(지정된 단축키 조합을 눌렀음)}//몇 가지 다른 키 값 판단에 주의하십시오://1>.단일 일반 키(예: A)//2>.단일 제어 키 + 단일 일반 키(예: Ctrl+A)//3>.다중 제어 키 + 단일 일반 키 (예: Ctrl + Alt + A)//위의 코드에서 2 를 보여 주었는데, 다른 상황은 이것으로 미루어 보면, 단지 몇 가지 조건을 더 넣고 다시 & 일어나면 된다
넷.전역 키보드를 사용하여 주의해야 할 문제를 감청합니다. (독자분들은 꼭 보십시오.)
1. 응용 프로그램에서 전역 키보드를 사용하여 감청하면 360에 발견되며, 탄창은 사용자에게 "키보드 입력을 감청하는 프로그램이 있는데 막으시겠습니까?"라고 알린다.
그래서 만약에 프로그램에서 Hook을 사용해야 한다면 사용자에게 정보를 누설하지 말라고 알려줘야 돼요.
아니면 그냥 App을 360 심사에 제출하세요.
그렇지 않으면 약하다는 힌트는 사용자 체험에 지대한 영향을 끼칠 수 있다

좋은 웹페이지 즐겨찾기