One interface that I hadn’t paid much attention to in TSF is ITfContextKeyEventSink. What does this let you do? Why, it lets you inspect keyboard input for a particular context (or document). This lets you do some really fun things, like redirect keyboard input from the current control and put it into another control. An example of this can be seen in the sample text service with candidate list, which, while it doesn’t really show how to use the ITfCandidateList interface (boo!), does show how to redirect keystrokes from the main document to the candidate window. Most of the fun is in CandidateList.cpp.
In the function CCandidateList::_StartCandidateList, the service creates a second context for the document, pushes it onto the context stack, then installs a ITfContextKeyEventSink on the new context (and a layout sink on the original context, so that the candidate window can track layout changes).
Then, in the functions CCandidateList::OnTestKeyDown and CCandidateList::OnTestKeyUp, the service intercepts the incoming keystrokes, and the functions CCandidateList::OnKeyDown and CCandidateList::OnKeyUp redirect the keystrokes to the candidate window.