using System;
using System.Windows.Forms;
using System.Runtime.InteropServices; //DLL import

namespace WindowsFormsApp
{
    public partial class Form1 : Form
    {
        [DllImport("user32.dll")] //C:\Windows\System32\user32.dll 참조
        private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc callback, IntPtr hInstance, uint threadId);

        [DllImport("user32.dll")]
        private static extern bool UnhookWindowsHookEx(IntPtr hInstance);

        [DllImport("user32.dll")]
        private static extern IntPtr CallNextHookEx(IntPtr idHook, int nCode, int wParam, IntPtr lParam);

        [DllImport("kernel32.dll")]
        private static extern IntPtr LoadLibrary(string lpFileName);

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

        //WM_Keydown
        //https://wiki.winehq.org/List_Of_Windows_Messages
        const int WH_KEYBOARD_LL = 13;
        const int WM_KEYDOWN = 256;
        const int WM_SYSKEYDOWN = 260;

        private static IntPtr hookId = IntPtr.Zero;

        public void SetHook()
        {
            IntPtr hInstance = LoadLibrary("User32");
            hookId = SetWindowsHookEx(WH_KEYBOARD_LL, lowLevelKeyboardProc, hInstance, 0);
        }

        public void UnHook()
        {
            UnhookWindowsHookEx(hookId);
        }

        public static IntPtr HookProc(int code, IntPtr wParam, IntPtr lParam)
        {
            if (code >= 0)
            {
                if (wParam == (IntPtr)WM_SYSKEYDOWN) //알트 키 눌림
                {
                    Keys key = (Keys)Marshal.ReadInt32(lParam);

                    if (key == Keys.PrintScreen)
                    {
                        MessageBox.Show("Alt + PrintScreen 키가 눌렸습니다.");
                        return (IntPtr)1; //1을 리턴하여 처리를 끝냅니다.
                    }
                }
                else if (wParam == (IntPtr)WM_KEYDOWN) //일반 키 눌림
                {
                    Keys key = (Keys)Marshal.ReadInt32(lParam);

                    switch (key)
                    {
                        case Keys.A:
                            MessageBox.Show("A키가 눌렸습니다.");
                            return (IntPtr)1;

                        default:
                            break;
                    }
                }
                
            }

            return CallNextHookEx(hookId, code, (int)wParam, lParam);
        }

        public Form1()
        {
            InitializeComponent();
            SetHook();
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            UnHook();
        }
    }
}

 

4개의 윈도우 API 함수가 필요하고 하는 일은 함수명을 보시면 짐작이 가실겁니다 ㅎㅎ

callback 함수에서 키에 대한 처리를 해주고 있는데

wParam는 어떤 타입의 키인지 정보가 들어있고 lParam 은 해당 키 값이 들어있습니다.

키값에 대해선 해당 주석 사이트에 나와있습니당!

+ Recent posts