WPF는 키보드 갈고리를 이용해 키보드를 포획하고 알려지지 않은 일을 하는데...전체 인스턴스

10318 단어
키보드 갈고리는 키보드 조작을 감시할 수 있는 지령이다.
이 말을 보고 사실 키보드 갈고리는 많은 일을 할 수 있다고 생각했지.
 
장면
당신의 프로그램이 전체적인 단축키를 필요로 할 때 키보드 갈고리를 사용할 수 있습니다. 예를 들어 사람들이 qq의 캡처 단축키를 자주 사용한다면 WPF에서 어떻게 실현합니까?
물론 윈도 창에 Key Down, Key Up을 직접 등록하는 것은 아니다. 이렇게 하면 프로그램이 초점인 상황에서만 터치할 수 있다.
우리가 여기서 해야 할 일은 더욱 강력하다. 즉, 비초점에서 키보드를 얻은 사건이다.
 
이루어지다
일단 저희가 이렇게 WinAPI가 많이 필요해요.
//        
        [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);

대략적인 논리는 다음과 같다.
키보드 갈고리를 설치한 후 의뢰를 통해 얻은 키보드 메시지를 처리합니다
 
두 가지 클래스로 정리(winapi[Win32Api.cs] 클래스와 키보드 갈고리[KeyboardHook.cs] 클래스)는 다음과 같다.
public class Win32Api
{
public const int WM_KEYDOWN = 0x100;

        public const int WM_KEYUP = 0x101;

        public const int WM_SYSKEYDOWN = 0x104;

        public const int WM_SYSKEYUP = 0x105;

        public const int WH_KEYBOARD_LL = 13;



        [StructLayout(LayoutKind.Sequential)] //             
        public class KeyboardHookStruct
        {

            public int vkCode; //     1 254        

            public int scanCode; //        

            public int flags;

            public int time;

            public int dwExtraInfo;

        }

public delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam);

        //        
        [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", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        public static extern IntPtr GetModuleHandle(string lpModuleName);
}
public class KeyboardHook
    {
        int hHook;

        Win32Api.HookProc KeyboardHookDelegate;


/// <summary>
        ///       
        /// </summary>
        public void SetHook()
        {

            KeyboardHookDelegate = new Win32Api.HookProc(KeyboardHookProc);

            ProcessModule cModule = Process.GetCurrentProcess().MainModule;

            var mh = Win32Api.GetModuleHandle(cModule.ModuleName);

            hHook = Win32Api.SetWindowsHookEx(Win32Api.WH_KEYBOARD_LL, KeyboardHookDelegate, mh, 0);

        }

        /// <summary>
        ///       
        /// </summary>
        public void UnHook()
        {

            Win32Api.UnhookWindowsHookEx(hHook);

        }
        
        /// <summary>
        ///       
        /// </summary>
        /// <param name="nCode"></param>
        /// <param name="wParam"></param>
        /// <param name="lParam"></param>
        /// <returns></returns>
        private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam)
        {
            //         (nCode<0
            if (nCode >= 0)
            {

                Win32Api.KeyboardHookStruct KeyDataFromHook = (Win32Api.KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(Win32Api.KeyboardHookStruct));

                int keyData = KeyDataFromHook.vkCode;

                //WM_KEYDOWN WM_SYSKEYDOWN  ,    OnKeyDownEvent  
                if (OnKeyDownEvent != null && (wParam == Win32Api.WM_KEYDOWN || wParam == Win32Api.WM_SYSKEYDOWN))
                {
                        //           
                        // keyData       ,      

                }

                //WM_KEYUP WM_SYSKEYUP  ,   OnKeyUpEvent   

                if (OnKeyUpEvent != null && (wParam == Win32Api.WM_KEYUP || wParam == Win32Api.WM_SYSKEYUP))
                {
                          //           
                }

            }

            return Win32Api.CallNextHookEx(hHook, nCode, wParam, lParam);

        }
}

 
당시에 가상 코드를 가져왔을 때 사실 나는 거절했다. 왜냐하면 다음에 나는 이 가상 코드에 대해 어떤 처리를 해야 할지 몰랐기 때문이다. 설마 하나하나 전환해야만 WPF에서 누르는 키가 무엇인지 진일보 판단할 수 있겠는가?
마지막으로 블로그 에 알리면 시스템에서.Windows.Input 네임스페이스에 변환 방법이 봉인되어 있음
namespace System.Windows.Input
{
    //   : 
    //         Win32      WPFSystem.Windows.Input.Key              。
    public static class KeyInterop
    {
        //   : 
        //       Win32        WPFSystem.Windows.Input.Key。
        //
        //   : 
        //   virtualKey:
        ////
        //     : 
        //     WPF  。
        public static Key KeyFromVirtualKey(int virtualKey);
        //
        //   : 
        //       WPFSystem.Windows.Input.Key     Win32    。
        //
        //   : 
        //   key:
        //          WPF。
        //
        //     : 
        //     Win32    。
        public static int VirtualKeyFromKey(Key key);
    }
}

 
결실
그래서 저희가 기우의 키보드 조작 기록을 즐겁게 받았어요.
KeyInterop.KeyFromVirtualKey(KeyData)

노노야, 난 그냥 피아노 건반을 만들었어.
 
코드가 이미 붙었으니, 기우에게 별도로 데모를 제공하지 않는 것을 용서하십시오

좋은 웹페이지 즐겨찾기