none
Keyboard Hook and Mouse Hook fail in PPT 2013 RRS feed

  • Question

  • Hi, I’m developing a ppt addin now and I tried to use Keyboard Hook and Mouse Hook for detecting when user is doing clicking or undo/redo (ctrl+c and ctrl+v). My code below works fine in PPT 2010 but not in PPT 2013.
    I use windows 8 x64, office 2010 x86, and office 2013 x86.

    Actually this problem is similar to HERE but the thread isn't really answered

    Here’s my source code:
    Keyboard Hook

    class InterceptKeys
    {
        private const int WH_KEYBOARD_LL = 13;
        private const int WH_KEYBOARD = 2;
        private const int WM_KEYDOWN = 0x0100;
        private const int WM_KEYUP = 0x0101;
        private static LowLevelKeyboardProc _proc = HookCallback;
        private static IntPtr _hookID = IntPtr.Zero;
    
        public static void Activate()
        {
            _hookID = SetHook(_proc);
        }
    
        public static void Deactivate()
        {
            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 delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
    
        private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
        {
            if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
            {
                int vkCode = Marshal.ReadInt32(lParam);
                // do something here
            }
    
            return CallNextHookEx(_hookID, nCode, wParam, lParam);
        }
    
        [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);
    }

    Mouse Hook  

    class InterceptMouse
    {
        private static LowLevelMouseProc _proc = HookCallback;
        private static IntPtr _hookID = IntPtr.Zero;
        private const int WH_MOUSE_LL = 14;
    
        private enum MouseMessages
        {
            WM_LBUTTONDOWN = 0x0201,
            WM_LBUTTONUP = 0x0202,
            WM_MOUSEMOVE = 0x0200,
            WM_MOUSEWHEEL = 0x020A,
            WM_RBUTTONDOWN = 0x0204,
            WM_RBUTTONUP = 0x0205
        }
    
        [StructLayout(LayoutKind.Sequential)]
        private struct POINT
        {
            public int x;
            public int y;
        }
    
        [StructLayout(LayoutKind.Sequential)]
        private struct MSLLHOOKSTRUCT
        {
            public POINT pt;
            public uint mouseData;
            public uint flags;
            public uint time;
            public IntPtr dwExtraInfo;
        }
    
        public static void Activate()
        {
            _hookID = SetHook(_proc);
        }
    
        public static void Deactivate()
        {
            UnhookWindowsHookEx(_hookID);
        }
    
        private static IntPtr SetHook(LowLevelMouseProc proc)
        {
            using (Process curProcess = Process.GetCurrentProcess())
            using (ProcessModule curModule = curProcess.MainModule)
            {
                return SetWindowsHookEx(WH_MOUSE_LL, proc, GetModuleHandle(curModule.ModuleName), 0);
            }
        }
    
        private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam);
    
        private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
        {
            if (nCode >= 0 && MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam)
            {
                MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
                // do something here
            }
            return CallNextHookEx(_hookID, nCode, wParam, lParam);
        }
    
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelMouseProc 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);
    }


    Calling  Activate() and Deactivate() are done when starting add-in and shutdown add-in

    private void ThisAddIn_Startup(object sender, System.EventArgs e)
    {
        InterceptKeys.Activate();
        InterceptMouse.Activate();
    }
    private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
    {
        // is called when ppt window is closed (x button)
        InterceptKeys.Deactivate();
        InterceptMouse.Deactivate();
    }

    Detail of the problems when testing it in PPT 2013

    • Both keyboard and mouse hook, are successful while calling _hookID = SetHook(_proc); Since value is _hookID  positive non-zero (not null)
    • In keyboard hook,  HookCallback(int nCode, IntPtr wParam, IntPtr lParam) is never triggered, while in Mouse hook, HookCallback is triggered.
    • When calling UnhookWindowsHookEx(IntPtr hhk) in mouse hook, PPT 2013 gets delay for 1-2 seconds for closing window, it unusually takes long time when doing unhook (it's said this is a bug when you try to unhook when clicking X close button). But if you unhook using button or other else it's just fine

    EDIT:

    I tested in another machine: Win 7 x64 and Office 2013 x64. Problems above are still remain also when i change the platform target (on project's properties) to x64 also is not helping. 


    Saturday, December 8, 2012 3:25 AM

All replies

  • Hi reza.adhitya,

    Thanks for posting in the MSDN Forum.

    I will involve some experts into your thread to see whether they can help you out. There might be some time delay, appreciate for your patience.

    Have a good day,

    Tom


    Tom Xu [MSFT]
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Monday, December 10, 2012 10:12 AM
    Moderator
  • Hi,

    Was this ever solved?

    I'm having the same issue in Excel 2013 and I cannot find another way of achieving the Hook.

    Regards

    Brian


    Brian Graham

    Thursday, June 27, 2013 4:09 AM