첨부 소스 코드는 나눔고딕코딩 폰트를 사용합니다.
728x90
반응형
728x170

TestProject.zip
0.01MB

▶ Program.cs

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

namespace TestProject
{
    /// <summary>
    /// 프로그램
    /// </summary>
    static class Program
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Delegate
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region 저수준 키보드 프로시저 대리자 - LowLevelKeyboardProc(code, wordParameter, longParameter)

        /// <summary>
        /// 저수준 키보드 프로시저 대리자
        /// </summary>
        /// <param name="code">코드</param>
        /// <param name="wordParameter">WORD 매개 변수</param>
        /// <param name="longParameter">LONG 매개 변수</param>
        /// <returns>처리 결과</returns>
        private delegate IntPtr LowLevelKeyboardProc(int code, IntPtr wordParameter, IntPtr longParameter);

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Import
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Private

        #region 윈도우 디스플레이 어피너티 설정하기 - SetWindowDisplayAffinity(windowHandle, affinity)

        /// <summary>
        /// 윈도우 디스플레이 어피너티 설정하기
        /// </summary>
        /// <param name="windowHandle">윈도우 핸들</param>
        /// <param name="affinity">어피너티</param>
        /// <returns>처리 결과</returns>
        [DllImport("user32.dll")]
        private static extern uint SetWindowDisplayAffinity(IntPtr windowHandle, uint affinity);

        #endregion
        #region 윈도우 후킹 설정하기 - SetWindowsHookEx(hookID, lowLevelKeyboardProcessDelegate, moduleHandle, threadID)

        /// <summary>
        /// 윈도우 후킹 설정하기
        /// </summary>
        /// <param name="hookID">후킹 ID</param>
        /// <param name="lowLevelKeyboardProc">저수준 키보드 처리 대리자</param>
        /// <param name="moduleHandle">모듈 핸들</param>
        /// <param name="threadID">쓰레드 ID</param>
        /// <returns>후킹 핸들</returns>
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr SetWindowsHookEx
        (
            int                  hookID,
            LowLevelKeyboardProc lowLevelKeyboardProc,
            IntPtr               moduleHandle,
            uint                 threadID
        );

        #endregion
        #region 윈도우 후킹 취소하기 - UnhookWindowsHookEx(hookHandle)

        /// <summary>
        /// 윈도우 후킹 취소하기
        /// </summary>
        /// <param name="hookHandle">후킹 핸들</param>
        /// <returns>처리 결과</returns>
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool UnhookWindowsHookEx(IntPtr hookHandle);

        #endregion
        #region 다음 후킹 호출하기 - CallNextHookEx(hookHandle, code, wordParameter, longParameter)

        /// <summary>
        /// 다음 후킹 호출하기
        /// </summary>
        /// <param name="hookHandle">후킹 핸들</param>
        /// <param name="code">코드</param>
        /// <param name="wordParameter">WORD 매개 변수</param>
        /// <param name="longParameter">LONG 매개 변수</param>
        /// <returns>후킹 핸들</returns>
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr CallNextHookEx(IntPtr hookHandle, int code, IntPtr wordParameter, IntPtr longParameter);

        #endregion
        #region 모듈 핸들 구하기 - GetModuleHandle(moduleName)

        /// <summary>
        /// 모듈 핸들 구하기
        /// </summary>
        /// <param name="moduleName">모듈명</param>
        /// <returns>모듈 핸들</returns>
        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr GetModuleHandle(string moduleName);

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// WH_KEYBOARD_LL
        /// </summary>
        private const int WH_KEYBOARD_LL = 13;

        /// <summary>
        /// WM_KEYDOWN
        /// </summary>
        private const int WM_KEYDOWN = 0x0100;

        /// <summary>
        /// WM_KEYUP
        /// </summary>
        private const int WM_KEYUP = 0x101;

        /// <summary>
        /// WDA_NONE
        /// </summary>
        private const uint WDA_NONE = 0;

        /// <summary>
        /// WDA_MONITOR
        /// </summary>
        private const uint WDA_MONITOR = 1;

        /// <summary>
        /// 저수준 키보드 프로시저 대리자
        /// </summary>
        private static LowLevelKeyboardProc _lowLevelKeyboardProc = HookCallback;

        /// <summary>
        /// 후킹 핸들
        /// </summary>
        private static IntPtr _hookHandle = IntPtr.Zero;

        /// <summary>
        /// 메인 폼
        /// </summary>
        private static MainForm _mainForm;

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Private

        #region 프로그램 시작하기 - Main()

        /// <summary>
        /// 프로그램 시작하기
        /// </summary>
        [STAThread]
        private static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            _hookHandle = SetHook(_lowLevelKeyboardProc);

            _mainForm = new MainForm();

            Application.Run(_mainForm);

            UnhookWindowsHookEx(_hookHandle);
        }

        #endregion

        #region 후킹 콜백 처리하기 - HookCallback(code, wordParameter, longParameter)

        /// <summary>
        /// 후킹 콜백 처리하기
        /// </summary>
        /// <param name="code">코드</param>
        /// <param name="wordParameter">WORD 매개 변수</param>
        /// <param name="longParameter">LONG 매개 변수</param>
        /// <returns>후킹 핸들</returns>
        private static IntPtr HookCallback(int code, IntPtr wordParameter, IntPtr longParameter)
        {
            if(code >= 0 && wordParameter == (IntPtr)WM_KEYDOWN)
            {
                int vkCode = Marshal.ReadInt32(longParameter);

                if(vkCode == 44) // PRINT SCREEN KEY
                {
                    SetWindowDisplayAffinity(_mainForm.Handle, WDA_MONITOR);

                    Console.WriteLine("KEYDOWN");
                    Console.WriteLine((Keys)vkCode);
                }
            }
            else if(code >= 0 && wordParameter == (IntPtr)WM_KEYUP)
            {
                int vkCode = Marshal.ReadInt32(longParameter);

                if(vkCode == 44) // PRINT SCREEN KEY
                {
                    SetWindowDisplayAffinity(_mainForm.Handle, WDA_NONE);

                    Console.WriteLine("KEYDOWN");
                    Console.WriteLine((Keys)vkCode);
                }
            }

            return CallNextHookEx(_hookHandle, code, wordParameter, longParameter);
        }

        #endregion
        #region 후킹 설정하기 - SetHook(lowLevelKeyboardProc)

        /// <summary>
        /// 후킹 설정하기
        /// </summary>
        /// <param name="lowLevelKeyboardProc">저수준 키보드 프로시저 대리자</param>
        /// <returns>후킹 핸들</returns>
        private static IntPtr SetHook(LowLevelKeyboardProc lowLevelKeyboardProc)
        {
            using(Process process = Process.GetCurrentProcess())
            {
                using(ProcessModule processModule = process.MainModule)
                {
                    return SetWindowsHookEx
                    (
                        WH_KEYBOARD_LL,
                        lowLevelKeyboardProc,
                        GetModuleHandle(processModule.ModuleName),
                        0
                    );
                }
            }
        }

        #endregion
    }
}
728x90
반응형
그리드형(광고전용)
Posted by icodebroker

댓글을 달아 주세요