2011-05-02 7 views
4

문자를 누르면 공간을 눌러 캡슐을 켜고 끄는 간단한 창 양식 응용 프로그램이 있습니다.배경 키 누름 수신기

문제는 내가 작동하도록 창에 집중해야한다는 것입니다. (최상위는 대부분 작동하지 않으며 최상위는 초점을 맞추지 않고 초점을 맞추지 않습니다).

누구나 메모장에 글을 쓰고 어떻게 작동시킬 수 있습니까?

답변

14

키 로깅은 장난 꾸러기 물건에 사용할 수 있으며 Caps Lock을 조작하는 것은 다소 이상하게 보일 수 있지만 이미 공개적으로 사용할 수 있으며 나보다 사용자 스토리를 잘 알고 있기 때문에 해결책을 게시했습니다.

다음은 MSDN 포럼의 keylogger code in C#에 게시 된 코드 스 니펫을 기반으로 한 예제입니다.

using System; 
using System.Diagnostics; 
using System.Runtime.InteropServices; 
using System.Windows.Forms; 

class Program 
{ 
    private const int WH_KEYBOARD_LL = 13; 
    private const int WM_KEYDOWN = 0x0100; 
    private static LowLevelKeyboardProc _proc = HookCallback; 
    private static IntPtr _hookID = IntPtr.Zero; 
    private static bool lastKeyWasLetter = false; 

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId); 

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    [return: MarshalAs(UnmanagedType.Bool)] 
    private static extern bool UnhookWindowsHookEx(IntPtr hhk); 

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam); 

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    private static extern IntPtr GetModuleHandle(string lpModuleName); 

    [DllImport("user32.dll")] 
    static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, UIntPtr dwExtraInfo); 

    private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam); 

    [STAThread] 
    static void Main(string[] args) 
    { 
     Application.EnableVisualStyles(); 
     Application.SetCompatibleTextRenderingDefault(false); 

     _hookID = SetHook(_proc); 
     Application.Run(); 

     UnhookWindowsHookEx(_hookID); 
    } 

    private static IntPtr SetHook(LowLevelKeyboardProc proc) 
    { 
     using (Process curProcess = Process.GetCurrentProcess()) 
     using (ProcessModule curModule = curProcess.MainModule) 
     { 
      return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0); 
     } 
    } 

    private static void ToggleCapsLock() 
    { 
     const int KEYEVENTF_EXTENDEDKEY = 0x1; 
     const int KEYEVENTF_KEYUP = 0x2; 

     UnhookWindowsHookEx(_hookID); 
     keybd_event(0x14, 0x45, KEYEVENTF_EXTENDEDKEY, (UIntPtr)0); 
     keybd_event(0x14, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, (UIntPtr)0); 
     _hookID = SetHook(_proc); 
    } 

    private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) 
    { 
     if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN) 
     { 
      if (lastKeyWasLetter) 
      { 
       if (Control.IsKeyLocked(System.Windows.Forms.Keys.CapsLock)) 
       { 
        ToggleCapsLock(); 
       } 
       lastKeyWasLetter = false; 
      } 
      Keys key = (Keys)Marshal.ReadInt32(lParam);    
      if (key == Keys.Space) 
      { 
       if (!Control.IsKeyLocked(System.Windows.Forms.Keys.CapsLock)) 
       { 
        ToggleCapsLock(); 
       } 
      } 
      else if (key >= Keys.A && key <= Keys.Z) 
      { 
       lastKeyWasLetter = true; 
      } 
     } 
     return CallNextHookEx(_hookID, nCode, wParam, lParam); 
    } 
} 

Visual Studio에서 새로운 Windows 응용 프로그램의 Program.cs로 붙여 넣습니다.

Caps Lock을 켜고 끄기 위해 키 작동 중지 이벤트를 가로 채면 응용 프로그램이 처리하기 전에 이벤트가 가로 채게됩니다. 즉, 문자 키를 누를 때 Caps Lock을 해제하면 입력 한 응용 프로그램이 공백을 넣은 직후에도 소문자를받을 수 있습니다.

각 단어의 첫 글자의 대문자 사용을 강요하고 있다고 가정 했으므로 (그렇다면 Return과 같은 다른 키도 처리해야 할 수도 있음) 내 스 니펫은 Caps Lock을 끕니다. 문자가 눌러 진 다음의 키 다운 이벤트. 빨리 입력 할 때 다음 키를 누를 때까지 초기 키를 누른 상태로 유지할 수 있기 때문에 키를 잡아서 포착 할 수는 없습니다.

+0

나는 이미 코드 프로젝트 1을 들여다 보았다. (그들은 내가하고 싶은 것보다 더 복잡한 것을했다.) 첫 번째 링크 –

+0

확인해 보겠습니다. 귀하의 목적에 맞는 MSDN 예제를 얻는 방법을 보여주기 위해 제 대답을 업데이트했습니다. – Ergwun

관련 문제