Обнаружение изменений текста в Word 2016 из надстройки VSTO

Этот вопрос очень тесно связан сКак получить событие «KeyPress» из надстройки Word 2010 (разработанной на C #)? (и фактически включает в себя пример кода из ответа на этот вопрос), но речь идет конкретно о разработке в Visual Studio (Professional) 2015 для Word 2016, работающей в Windows 10.

Я пытаюсь определить, когда текст изменяется в документе Word из надстройки VSTO. Я понимаю из

Как получить событие «KeyPress» из надстройки Word 2010 (разработанной на C #)? (14 ноября 2011 г.)Захват события нажатия клавиш MS Word с использованием C # (21 октября 2012 г.)Как поднять событие на MS Word Keypress (24 октября 2012 г.)Как перехватить событие нажатия клавиши в MSword с помощью VSTO? (5 ноября 2012 г.)

что нет никакого управляемого событиями способа сделать это. Word просто не отправляет события при изменении текста.

Я видел два обсуждаемых обходных пути:

ИспользоватьWindowSelectionChange событие. К сожалению, это событие, похоже, отправляется, когда выбор изменяется путем нажатия клавиш со стрелками, использования мыши, выполнения отмен или повторного выполнения и, возможно, других действий, но не при вводе или удалении.Используйте низкоуровневый хук события нажатия клавиш. Это обсуждалось в нескольких из этих вопросов StackOverflow, и также было названо «широко распространенной техникой» вветка на форуме Visual Studio в феврале 2014 г.

Я пытаюсь использовать код в ответ наКак получить событие «KeyPress» из надстройки Word 2010 (разработанной на C #)?и, кажется, наблюдает каждое событиеКроме отправленные на Word 2016

Вот код, который я использую, для удобства пользования.

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

namespace KeydownWordAddIn
{
    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 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(() => {
                    Debug.WriteLine(pressedKey);
                });
                thread.Start();
            }
            return CallNextHookEx(hookId, nCode, wParam, lParam);
        }

        private void ThisAddIn_Startup(object sender, EventArgs e)
        {
            hookId = SetHook(procedure);
        }

        private void ThisAddIn_Shutdown(object sender, EventArgs e)
        {
            UnhookWindowsHookEx(hookId);
        }

        #region VSTO generated code
        /// <summary>
        /// Required method for Designer support.
        /// </summary>
        private void InternalStartup()
        {
            this.Startup += new System.EventHandler(ThisAddIn_Startup);
            this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
        }
        #endregion
    }
}

Когда я запускаю Word 2016 с этой надстройкой, я вижу события нажатия клавиш, отправляемые в браузер Edge и даже в Visual Studio, но не в сам Word.

В Word 2016 каким-то образом предотвращается перехват клавиш или я делаю что-то не так?

Ответы на вопрос(2)

Ваш ответ на вопрос