How to get the “KeyPress” event from a Word 2010 Addin (developed in C#)?

后端 未结 2 1219
礼貌的吻别
礼貌的吻别 2020-11-30 12:45

How can I \"catch\" the KeyPress event from a Word 2010 Addin developed in C#?

Note: I\'m not looking for \"complex\" solutions like hooking stuff, but for the nice

相关标签:
2条回答
  • 2020-11-30 13:02

    Unfortunately there is nothing built-in in the Word API or VSTO which can pick up key strokes, more info on this can be found here

    I've been searching for a feasible solution for some time but the best I could come up with was handling it through Windows API using hooks, it's likely you will reach the same conclusion so here's an example:

    You'll need to add a using directive to the following assemblies:

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

    And here's the hook:

       public partial class ThisAddIn
        {
            private const int WH_KEYBOARD_LL = 13;
            private const int WM_KEYDOWN = 0x0100;
    
            private static IntPtr hookId = IntPtr.Zero;
            private delegate IntPtr HookProcedure(int nCode, IntPtr wParam, IntPtr lParam);
            private static HookProcedure procedure = HookCallback;
    
            [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            private static extern IntPtr GetModuleHandle(string lpModuleName);
    
            [DllImport("user32.dll", SetLastError = true)]
            private static extern bool UnhookWindowsHookEx(IntPtr hhk);
    
            [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            private static extern IntPtr SetWindowsHookEx(int idHook, HookProcedure lpfn, IntPtr hMod, uint dwThreadId);
    
            [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
            private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);  
    
            private void ThisAddIn_Startup(object sender, System.EventArgs e)
            {
                hookId = SetHook(procedure);
            }
    
            private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
            {
                UnhookWindowsHookEx(hookId);
            }
    
            private static IntPtr SetHook(HookProcedure procedure)
            {
                using (Process process = Process.GetCurrentProcess())
                using (ProcessModule module = process.MainModule)
                    return SetWindowsHookEx(WH_KEYBOARD_LL, procedure, GetModuleHandle(module.ModuleName), 0);
            }
    
            private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
            {
                if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
                {
                    int pointerCode = Marshal.ReadInt32(lParam);
                    string pressedKey = ((Keys)pointerCode).ToString();
    
                    //Do some sort of processing on key press
                    var thread = new Thread(() => { MessageBox.Show(pressedKey); });
                    thread.Start();
                }
                return CallNextHookEx(hookId, nCode, wParam, lParam);
            }
    
            private void InternalStartup()
            {
                this.Startup += new System.EventHandler(ThisAddIn_Startup);
                this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
            }
        }
    
    0 讨论(0)
  • 2020-11-30 13:10

    You might try to use the Excel WebBrowser Control instead of the System.Windows.Forms WebBrowser; it handles special key forwarding as TAB, DEL, CTRL+V, etc.

    For that change the WebBrowser contructor from

    new System.Windows.Forms.WebBrowser();
    

    to

    new Microsoft.Office.Tools.Excel.Controls.WebBrowser();  
    

    You would need to add references to your project: Project/Add Reference/Extensions select Microsoft.Tools.Outlook & Microsoft.Tools.Outlook.v4.0.Utilities

    0 讨论(0)
提交回复
热议问题