I want to write a word addin that does some computations and updates some ui whenever the user types something or moves the current insertion point. From looking at the MSDN docs, I don't see any obvious way such as an TextTyped event on the document or application objects.

Does anyone know if this is possible without polling the document?


As you've probably discovered, Word has events, but they're for really coarse actions like a document open or a switch to another document. I'm guessing MS did this intentionally to prevent a crappy macro from slowing down typing.

In short, there's no great way to do what you want. A Word MVP confirms that in this thread.

Wayne Kao
It turns out that this is possible but only by using low level keyboard hooks, and an out of process low level mouse hook.
Ben Childs
+1  A: 

Actually there is a way to run some code when a word has been typed, you can use SmartTags, and override the Recognize method, this method will be called whenever a word is type, which means whenever the user typed some text and hit the space, tab, or enter keys.

one problem with this however is that if you change the text using "Range.Text" it will detect it as a word change and call the function so it can cause infinite loops.

Here is some code I used to achieve this:

public class AutoBrandSmartTag : SmartTag

    Microsoft.Office.Interop.Word.Document cDoc;

    Microsoft.Office.Tools.Word.Action act = new Microsoft.Office.Tools.Word.Action("Test Action");

    public AutoBrandSmartTag(AutoBrandEngine.AutoBrandEngine _engine, Microsoft.Office.Interop.Word.Document _doc)
        : base("", "AutoBrand SmartTag")
        this.cDoc = _doc;

        this.Actions = new Microsoft.Office.Tools.Word.Action[] { act };

    protected override void Recognize(string text, Microsoft.Office.Interop.SmartTag.ISmartTagRecognizerSite site, 
        Microsoft.Office.Interop.SmartTag.ISmartTagTokenList tokenList)
        if (tokenList.Count < 1)

        int start = 0;
        int length = 0;
        int index = tokenList.Count > 1 ? tokenList.Count - 1 : 1;

        ISmartTagToken token = tokenList.get_Item(index);

        start = token.Start;
        length = token.Length;

Sebastian Bender