<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>TSF Aware : Applications</title><link>http://blogs.msdn.com/tsfaware/archive/tags/Applications/default.aspx</link><description>Tags: Applications</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Where are the TSF Samples?</title><link>http://blogs.msdn.com/tsfaware/archive/2008/10/22/where-are-the-tsf-samples.aspx</link><pubDate>Wed, 22 Oct 2008 23:57:41 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9011695</guid><dc:creator>Eric Brown</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/tsfaware/comments/9011695.aspx</comments><wfw:commentRss>http://blogs.msdn.com/tsfaware/commentrss.aspx?PostID=9011695</wfw:commentRss><wfw:comment>http://blogs.msdn.com/tsfaware/rsscomments.aspx?PostID=9011695</wfw:comment><description>&lt;p&gt;Many people have emailed me asking about the TSF samples on MSDN.&amp;#160; They’re supposed to be on MSDN code gallery, although they don’t appear to be there.&lt;/p&gt;  &lt;p&gt;They are, however, part of the &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=F26B1AA4-741A-433A-9BE5-FA919850BDBF&amp;amp;displaylang=en"&gt;Windows SDK&lt;/a&gt;. After installation, you'll find them in %programfiles%\Microsoft SDKs\Windows\v6.1\Samples\winui\Input\tsf.&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;There are actually more samples in the Windows SDK than were on MSDN, including some examples of how to write a text store, as well as how to interact with TSF in UILess mode.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9011695" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/tsfaware/archive/tags/tsf/default.aspx">tsf</category><category domain="http://blogs.msdn.com/tsfaware/archive/tags/Text+Services/default.aspx">Text Services</category><category domain="http://blogs.msdn.com/tsfaware/archive/tags/Applications/default.aspx">Applications</category><category domain="http://blogs.msdn.com/tsfaware/archive/tags/TSF+Manager/default.aspx">TSF Manager</category></item><item><title>Things the Documentation left out, part N</title><link>http://blogs.msdn.com/tsfaware/archive/2007/12/22/things-the-documentation-left-out-part-n.aspx</link><pubDate>Sat, 22 Dec 2007 18:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:6831043</guid><dc:creator>Eric Brown</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/tsfaware/comments/6831043.aspx</comments><wfw:commentRss>http://blogs.msdn.com/tsfaware/commentrss.aspx?PostID=6831043</wfw:commentRss><wfw:comment>http://blogs.msdn.com/tsfaware/rsscomments.aspx?PostID=6831043</wfw:comment><description>&lt;P&gt;I recently had two people ask me the same question:&lt;/P&gt;
&lt;P&gt;"Why can't I insert more than one character into a composition on Notepad?"&lt;/P&gt;
&lt;P&gt;It's actually a bit more complicated than that, since this behavior only appears to happen on Windows XP with a US English text service.&amp;nbsp; (Japanese text services appear to work correctly.)&lt;/P&gt;
&lt;P&gt;I just had a chance to figure out what was going on here, and, since it doesn't seem to be documented anywhere else, I thought I'd post the answer so that the next poor sod doesn't have to spend eternity scratching his head wondering why he can't get it to work.&lt;/P&gt;
&lt;P&gt;After a longish debugging bout, and a bunch of searching through the XP source code, I have the answer.&lt;/P&gt;
&lt;P&gt;The answer is that there's a Text Event Sink attached to the TSF-unaware context, and when the context changes, this event sink looks to see if the changed text has the GUID_PROP_COMPOSING property attached to it.&amp;nbsp; If it doesn't, it terminates the composition.&lt;/P&gt;
&lt;P&gt;So, if you want to have your text services insert more than one character into a composition, you need to make sure that your text has the GUID_PROP_COMPOSING property set to 1.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;I had previously written some code to manage this property.&amp;nbsp; However, you cannot explicitly set the GUID_PROP_COMPOSING property -&lt;/P&gt;
&lt;P&gt;ITfProperty::SetValue() will return TF_E_READONLY if you do.&lt;/P&gt;
&lt;P&gt;What you &lt;STRONG&gt;do&lt;/STRONG&gt; need to do is use the ITfComposition::ShiftStart and ITfComposition::ShiftEnd methods to move the start and ending points of your composition to cover the text.&amp;nbsp; These methods will update the GUID_PROP_COMPOSING property directly.&lt;/P&gt;
&lt;P&gt;&lt;STRIKE&gt;The code to do that would look like this:&lt;/STRIKE&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;STRIKE&gt;&lt;/STRIKE&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;STRIKE&gt;BOOL CTextService::_SetCompositionComposing(TfEditCookie ec, ITfContext *pContext)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ITfRange *pRangeComposition;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ITfProperty *pComposingProperty;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; HRESULT hr; &lt;/STRIKE&gt;
&lt;P&gt;&lt;STRIKE&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // the composition requires a range and the context it lives in&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (_pComposition-&amp;gt;GetRange(&amp;amp;pRangeComposition) != S_OK)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return FALSE; &lt;/STRIKE&gt;
&lt;P&gt;&lt;STRIKE&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; hr = E_FAIL; &lt;/STRIKE&gt;
&lt;P&gt;&lt;STRIKE&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // get our the display attribute property&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (pContext-&amp;gt;GetProperty(GUID_PROP_COMPOSING, &amp;amp;pComposingProperty) == S_OK)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; VARIANT var;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // set the value over the range&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var.vt = VT_I4; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var.lVal = 1; &lt;/STRIKE&gt;
&lt;P&gt;&lt;STRIKE&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; hr = pComposingProperty-&amp;gt;SetValue(ec, pRangeComposition, &amp;amp;var); &lt;/STRIKE&gt;
&lt;P&gt;&lt;STRIKE&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; pComposingProperty-&amp;gt;Release();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/STRIKE&gt;
&lt;P&gt;&lt;STRIKE&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; pRangeComposition-&amp;gt;Release();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return (hr == S_OK);&lt;BR&gt;} &lt;/STRIKE&gt;
&lt;P&gt;&lt;STRIKE&gt;When you're ready to finalize your composition, you should clear the property over the composed text by calling ITfProperty::Clear(). &lt;/STRIKE&gt;
&lt;P&gt;Note that none of the sample text services do this.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=6831043" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/tsfaware/archive/tags/Text+Services/default.aspx">Text Services</category><category domain="http://blogs.msdn.com/tsfaware/archive/tags/Applications/default.aspx">Applications</category></item><item><title>Oops!</title><link>http://blogs.msdn.com/tsfaware/archive/2007/11/14/oops.aspx</link><pubDate>Wed, 14 Nov 2007 21:01:48 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:6219479</guid><dc:creator>Eric Brown</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/tsfaware/comments/6219479.aspx</comments><wfw:commentRss>http://blogs.msdn.com/tsfaware/commentrss.aspx?PostID=6219479</wfw:commentRss><wfw:comment>http://blogs.msdn.com/tsfaware/rsscomments.aspx?PostID=6219479</wfw:comment><description>&lt;p&gt;If you've tried to use the modified version of Scintilla that I described in my &lt;a href="http://msdn.microsoft.com/msdnmag/issues/07/07/Dictation/"&gt;MSDN article&lt;/a&gt;, you will find that the zipped sources don't actually have the changes that I made.&amp;nbsp; That was my fault; when I was packaging the sources, I had two versions of ScintillaWin.cxx around, and I picked the newer one, which (sigh) was the wrong one.&amp;nbsp; Anyway, here's a link to the correct version of &lt;a href="http://cid-c57822bc3c7d1873.skydrive.live.com/self.aspx/Public/ScintillaWin.cxx"&gt;ScintillaWin.cxx with TSF support&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=6219479" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/tsfaware/archive/tags/tsf/default.aspx">tsf</category><category domain="http://blogs.msdn.com/tsfaware/archive/tags/dictation/default.aspx">dictation</category><category domain="http://blogs.msdn.com/tsfaware/archive/tags/Applications/default.aspx">Applications</category></item><item><title>Input Scopes</title><link>http://blogs.msdn.com/tsfaware/archive/2007/07/10/input-scopes.aspx</link><pubDate>Tue, 10 Jul 2007 17:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:3787583</guid><dc:creator>Eric Brown</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/tsfaware/comments/3787583.aspx</comments><wfw:commentRss>http://blogs.msdn.com/tsfaware/commentrss.aspx?PostID=3787583</wfw:commentRss><wfw:comment>http://blogs.msdn.com/tsfaware/rsscomments.aspx?PostID=3787583</wfw:comment><description>&lt;P&gt;Another useful, but underutilized, group of functions in TSF are those relating to Input Scopes.&amp;nbsp;&amp;nbsp; Input Scopes allow an application to define the sorts of things that are expected in this document (edit control, etc.).&amp;nbsp; For example, the Internet Explorer 7 address bar has an input scope of IS_URL | IS_DEFAULT | IS_ENUMSTRING - meaning that the address bar expects the input to be either a URL, one of the entries in its enumeration, or just plain anything (IE will default to searching for the string you typed).&amp;nbsp; &lt;/P&gt;
&lt;P&gt;Input scopes were originally created for the Tablet PC, and a lot of the MSDN documentation is specifically related to the Tablet PC.&amp;nbsp; However, other input handlers (for example, speech) use input scopes as well to improve recognition.&amp;nbsp;&amp;nbsp; For example, Windows Speech Recognition has a custom URL language model that is used when a control specifies the IS_URL input scope.&amp;nbsp; This significantly improves recognitions on URLs that are part of the language model.&lt;/P&gt;
&lt;P&gt;The functions are very easy to use, if you have an hwnd for your control.&amp;nbsp; If you only want to set a single input scope (for example, IS_DIGITS for a numeric control), then &lt;A href="http://msdn2.microsoft.com/en-us/library/ms629025.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms629025.aspx"&gt;SetInputScope&lt;/A&gt;&amp;nbsp;is the function for you.&amp;nbsp; If you want to set multiple input scopes, or you want to use one of the more exotic input scopes like IS_PHRASELIST or IS_REGULAREXPRESSION (which return application-defined strings), then you will want to use &lt;A href="http://msdn2.microsoft.com/en-us/library/ms629026.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms629026.aspx"&gt;SetInputScopes&lt;/A&gt;, which allows you to pass an array of input scopes, along with other data.&amp;nbsp; Finally, Windows Vista adds &lt;A href="http://msdn2.microsoft.com/en-us/library/aa383417.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/aa383417.aspx"&gt;SetInputScopes2&lt;/A&gt;, which is a variant of the SetInputScopes function, but which takes a string enumerator object instead of an array of strings.&lt;/P&gt;
&lt;P&gt;One thing to take note is that if you call &lt;STRONG&gt;SetInputScope&lt;/STRONG&gt; (or one of its siblings), you need to call SetInputScope(hwnd, IS_DEFAULT) before the window is destroyed.&amp;nbsp; MSDN mentions this in the remarks; I want to emphasize it.&lt;/P&gt;
&lt;P&gt;If your control doesn't have an hwnd, or if you want to have multiple input scopes per document, the situation is a bit more complicated.&amp;nbsp;&amp;nbsp; MSDN&amp;nbsp;isn't very clear about how to make input scopes work in TSF-aware applications.&amp;nbsp; In the&amp;nbsp;description of the &lt;A href="http://msdn2.microsoft.com/en-us/library/ms628582.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms628582.aspx"&gt;ITfInputScope&lt;/A&gt; interface, MSDN&amp;nbsp;says&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;A TSF-aware application does not call &lt;B&gt;SetInputScope&lt;/B&gt; directly, but rather implements either &lt;A href="http://msdn2.microsoft.com/ms538384.aspx" mce_href="http://msdn2.microsoft.com/ms538384.aspx"&gt;ITextStoreACP&lt;/A&gt; or &lt;A href="http://msdn2.microsoft.com/ms538731.aspx" mce_href="http://msdn2.microsoft.com/ms538731.aspx"&gt;ITfContextOwner&lt;/A&gt; to get a pointer to &lt;B&gt;&lt;A href="http://msdn2.microsoft.com/en-us/library/ms628582.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms628582.aspx"&gt;ITfInputScope&lt;/A&gt;&lt;/B&gt;.&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;What this bit means is that TSF-aware applications need to implement input scopes via&amp;nbsp;an application property.&amp;nbsp; In particular, you need to implement &lt;A href="http://msdn2.microsoft.com/en-us/library/ms538448.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms538448.aspx"&gt;ITextStoreACP::RequestSupportedAttrs&lt;/A&gt;, and &lt;A href="http://msdn2.microsoft.com/en-us/library/ms538449.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms538449.aspx"&gt;ITextStoreACP::RetrieveRequestedAttrs&lt;/A&gt;.&amp;nbsp; If you want to have multiple input scopes per document, then you also need to implement &lt;A href="http://msdn2.microsoft.com/en-us/library/ms538445.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms538445.aspx"&gt;ITextStoreACP::RequestAttrsAtPosition&lt;/A&gt;.&amp;nbsp; Note that the documentation refers to &lt;A href="http://msdn2.microsoft.com/en-us/library/ms629205.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms629205.aspx"&gt;TS_ATTRIDs&lt;/A&gt;; these are typedefs for GUIDs!&amp;nbsp; The TS_ATTRID that you need to support for input scopes is GUID_PROP_INPUTSCOPE&amp;nbsp; (you may, of course, add support for other TS_ATTRIDs).&amp;nbsp; &lt;/P&gt;
&lt;P&gt;Retrieving input scopes is fairly straightforward.&amp;nbsp;&amp;nbsp;MSDN has a&amp;nbsp;nice code snippet describing how to retrieve the &lt;A href="http://msdn2.microsoft.com/en-us/library/ms628582.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms628582.aspx"&gt;ITfInputScope&lt;/A&gt; interface here; once you have it, use &lt;A href="http://msdn2.microsoft.com/en-us/library/ms628585.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms628585.aspx"&gt;ITfInputScope::GetInputScopes&lt;/A&gt; to retrieve the list of input scopes, and the other methods return auxiliary data for exotic input scopes.&lt;/P&gt;
&lt;P&gt;If you&amp;nbsp;need the&amp;nbsp;string enumerator&amp;nbsp;(i.e., you want to support IS_ENUMSTRING), then you need to get the &lt;A href="http://msdn2.microsoft.com/en-us/library/aa382054.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/aa382054.aspx"&gt;ITfInputScope2&lt;/A&gt; interface, instead of&amp;nbsp;&lt;A href="http://msdn2.microsoft.com/en-us/library/ms628582.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms628582.aspx"&gt;ITfInputScope&lt;/A&gt;; all you need to do is QI the application property for IID_ITfInputScope2&amp;nbsp;instead of IID_ITfInputScope.&amp;nbsp; &amp;nbsp;The MSDN documentation for &lt;A href="http://msdn2.microsoft.com/en-us/library/aa382054.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/aa382054.aspx"&gt;ITfInputScope2&lt;/A&gt; is incorrect; ITfInputScope2 extends &lt;A href="http://msdn2.microsoft.com/en-us/library/ms628582.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms628582.aspx"&gt;ITfInputScope&lt;/A&gt;, not IUnknown (and it's only available on Windows Vista).&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/P&gt;
&lt;P&gt;The &lt;A href="http://msdn2.microsoft.com/en-us/library/ms538181.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms538181.aspx"&gt;Input Scope enumerations&lt;/A&gt; are defined &lt;A href="http://msdn2.microsoft.com/en-us/library/ms538181.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms538181.aspx"&gt;here&lt;/A&gt;.&amp;nbsp; &lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=3787583" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/tsfaware/archive/tags/Text+Services/default.aspx">Text Services</category><category domain="http://blogs.msdn.com/tsfaware/archive/tags/Applications/default.aspx">Applications</category></item><item><title>How do I use RichEdit 4.1?</title><link>http://blogs.msdn.com/tsfaware/archive/2007/06/14/how-do-i-use-richedit-4-1.aspx</link><pubDate>Thu, 14 Jun 2007 21:18:56 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:3294773</guid><dc:creator>Eric Brown</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/tsfaware/comments/3294773.aspx</comments><wfw:commentRss>http://blogs.msdn.com/tsfaware/commentrss.aspx?PostID=3294773</wfw:commentRss><wfw:comment>http://blogs.msdn.com/tsfaware/rsscomments.aspx?PostID=3294773</wfw:comment><description>&lt;p&gt;Another thing I didn't talk about in my article was how to make sure your rich text edit controls are based on RichEdit 4.1 (which has TSF support).&amp;nbsp; &lt;p&gt;You need to do two things: &lt;p&gt;1)&amp;nbsp; change your window class name from RICHEDIT_CLASS to MSFTEDIT_CLASS, and &lt;p&gt;2)&amp;nbsp; LoadLibrary("msftedit.dll") instead of LoadLibrary("richedit.dll"). &lt;p&gt;That's it!&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=3294773" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/tsfaware/archive/tags/dictation/default.aspx">dictation</category><category domain="http://blogs.msdn.com/tsfaware/archive/tags/Applications/default.aspx">Applications</category></item><item><title>Easy Dictation support for Windowless RichEdit controls</title><link>http://blogs.msdn.com/tsfaware/archive/2007/06/12/easy-dictation-support-for-windowless-richedit-controls.aspx</link><pubDate>Tue, 12 Jun 2007 17:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:3233002</guid><dc:creator>Eric Brown</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/tsfaware/comments/3233002.aspx</comments><wfw:commentRss>http://blogs.msdn.com/tsfaware/commentrss.aspx?PostID=3233002</wfw:commentRss><wfw:comment>http://blogs.msdn.com/tsfaware/rsscomments.aspx?PostID=3233002</wfw:comment><description>&lt;P&gt;In my article in MSDN, I mention that there are some easy ways to enable dictation support in controls that don't normally support dictation.&amp;nbsp; All the methods I described assume that the control has a window.&amp;nbsp; There is a way to enable dictation support for windowless rich text edit controls, assuming that you are using the RichEdit 4.1 implementation of&amp;nbsp;&lt;A href="http://msdn2.microsoft.com/en-us/library/ms651303.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms651303.aspx"&gt;ITextServices&lt;/A&gt;.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;I did not include this method in my article because I didn't want to include all the details about ITextServices, how you get an instance, and so forth.&amp;nbsp; I assume that if you already have an existing windowless rich edit control that uses ITextServices, you already know all that.&amp;nbsp; (If you don't, there's a quick primer available at &lt;A href="http://www.codeproject.com/richedit/RichDrawText.asp" mce_href="http://www.codeproject.com/richedit/RichDrawText.asp"&gt;CodeProject&lt;/A&gt;; note that I haven't actually used this code, and cannot vouch for it.)&lt;/P&gt;
&lt;P&gt;Anyway, if you have an ITextServices interface pointer, then you can enable TSF support (and, by extension, dictation support), by calling &lt;A href="http://msdn2.microsoft.com/en-us/library/ms651335.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms651335.aspx"&gt;ITextServices::TxSendMessage&lt;/A&gt;(&lt;A href="http://msdn2.microsoft.com/en-us/library/ms652071.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms652071.aspx"&gt;EM_SETEDITSTYLE&lt;/A&gt;, SES_USECTF, SES_USECTF).&lt;/P&gt;
&lt;P&gt;I hope that more richedit users will enable TSF support, so that users will have an easier time using dictation.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=3233002" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/tsfaware/archive/tags/dictation/default.aspx">dictation</category><category domain="http://blogs.msdn.com/tsfaware/archive/tags/Applications/default.aspx">Applications</category></item><item><title>Published!</title><link>http://blogs.msdn.com/tsfaware/archive/2007/06/09/published.aspx</link><pubDate>Sat, 09 Jun 2007 21:01:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:3187265</guid><dc:creator>Eric Brown</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/tsfaware/comments/3187265.aspx</comments><wfw:commentRss>http://blogs.msdn.com/tsfaware/commentrss.aspx?PostID=3187265</wfw:commentRss><wfw:comment>http://blogs.msdn.com/tsfaware/rsscomments.aspx?PostID=3187265</wfw:comment><description>&lt;P&gt;You might have noticed that I haven't really talked about text stores on this blog.&amp;nbsp; That's because I've been working on an article for MSDN Magazine on just that very subject.&amp;nbsp; It's in the July 2007 issue, and I just got my copy in the mail, so if you're a subscriber, you can read all the gory details about how to add TSF support to your controls and applications, complete with a working example.&lt;/P&gt;
&lt;P&gt;&lt;STRIKE&gt;&amp;nbsp;The article isn't currently available online yet - I'll add a link to the article as soon as it's available.&lt;/STRIKE&gt;&lt;/P&gt;
&lt;P&gt;Update:&amp;nbsp; The article is now online, and you can find it &lt;A class="" href="http://msdn.microsoft.com/msdnmag/issues/07/07/Dictation/default.aspx" mce_href="http://msdn.microsoft.com/msdnmag/issues/07/07/Dictation/default.aspx"&gt;here&lt;/A&gt;.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=3187265" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/tsfaware/archive/tags/tsf/default.aspx">tsf</category><category domain="http://blogs.msdn.com/tsfaware/archive/tags/Applications/default.aspx">Applications</category></item><item><title>Generating Candidates from an Application</title><link>http://blogs.msdn.com/tsfaware/archive/2007/05/25/generating-candidates-from-an-application.aspx</link><pubDate>Fri, 25 May 2007 21:43:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:2878099</guid><dc:creator>Eric Brown</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/tsfaware/comments/2878099.aspx</comments><wfw:commentRss>http://blogs.msdn.com/tsfaware/commentrss.aspx?PostID=2878099</wfw:commentRss><wfw:comment>http://blogs.msdn.com/tsfaware/rsscomments.aspx?PostID=2878099</wfw:comment><description>&lt;P&gt;Kirby left a comment to my post on &lt;A href="http://blogs.msdn.com/tsfaware/archive/2007/05/14/text-services-candidates.aspx" mce_href="http://blogs.msdn.com/tsfaware/archive/2007/05/14/text-services-candidates.aspx"&gt;candidates&lt;/A&gt;&amp;nbsp;asking when a text service should create an ITfCandidateList.&lt;/P&gt;
&lt;P&gt;The answer is that when the &lt;EM&gt;text service&lt;/EM&gt; wants to show candidates (via a &lt;A href="http://msdn2.microsoft.com/library/ms628684.aspx" mce_href="http://msdn2.microsoft.com/library/ms628684.aspx"&gt;preserved key&lt;/A&gt; or other mechanism), it should show its modal UI, and quite possibly may wish to push a new context so that the modal UI can be keyboard enabled (the &lt;A href="http://msdn.microsoft.com/archive/en-us/samples/internet/TextServicesFrameWork/CandidateList/default.asp" mce_href="http://msdn.microsoft.com/archive/en-us/samples/internet/TextServicesFrameWork/CandidateList/default.asp"&gt;sample&lt;/A&gt; does this).&amp;nbsp; &lt;/P&gt;
&lt;P&gt;The thing to note here is that ITfCandidateList is not involved here.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;So when &lt;EM&gt;does&lt;/EM&gt; the text service use ITfCandidateList?&amp;nbsp; When the &lt;STRONG&gt;application&lt;/STRONG&gt; wants to show candidates.&lt;/P&gt;
&lt;P&gt;How does this work?&amp;nbsp; Well, it's pretty complicated, but I'll try to outline the steps here.&amp;nbsp; (Get ready, it's going to get a little wild...)&lt;/P&gt;
&lt;H2&gt;The big blocks &lt;/H2&gt;
&lt;P&gt;1)&amp;nbsp; Application gets &lt;A href="http://msdn2.microsoft.com/library/ms538970.aspx" mce_href="http://msdn2.microsoft.com/library/ms538970.aspx"&gt;ITfFnReconversion&lt;/A&gt; interface.&lt;/P&gt;
&lt;P&gt;2)&amp;nbsp; Application gets&amp;nbsp;target range (&lt;A href="http://msdn2.microsoft.com/library/ms538388.aspx" mce_href="http://msdn2.microsoft.com/library/ms538388.aspx"&gt;ITextStoreACPServices::CreateRange&lt;/A&gt; comes in very handy here).&lt;/P&gt;
&lt;P&gt;3)&amp;nbsp; Application calls &lt;A href="http://msdn2.microsoft.com/library/ms538973.aspx" mce_href="http://msdn2.microsoft.com/library/ms538973.aspx"&gt;ITfFnReconversion::QueryRange&lt;/A&gt; to transform the target range.&lt;/P&gt;
&lt;P&gt;4)&amp;nbsp; Application calls &lt;A href="http://msdn2.microsoft.com/library/ms538972.aspx" mce_href="http://msdn2.microsoft.com/library/ms538972.aspx"&gt;ITfFnReconversion::GetReconversion&lt;/A&gt; to get the list of candidates.&lt;/P&gt;
&lt;P&gt;5)&amp;nbsp; Application displays candidate list (e.g., in context menu, dialog, what have you).&lt;/P&gt;
&lt;P&gt;6)&amp;nbsp; Application calls &lt;A href="http://msdn2.microsoft.com/library/ms538496.aspx" mce_href="http://msdn2.microsoft.com/library/ms538496.aspx"&gt;ITfCandidateList::SetResult&lt;/A&gt;() when the selection is selected.&lt;/P&gt;
&lt;P&gt;7)&amp;nbsp; Application releases candidate list, reconversion interface, and does other cleanup.&lt;/P&gt;
&lt;P&gt;Alternatively, if the application wants to let the text service manage the UI, it can call &lt;A href="http://msdn2.microsoft.com/library/ms538975.aspx" mce_href="http://msdn2.microsoft.com/library/ms538975.aspx"&gt;ITfFnReconversion::Reconvert&lt;/A&gt; at step 4 and step out of the way.&amp;nbsp;&amp;nbsp; (Note that not all text services implement this, as this function must not wait for the UI to be dismissed before returning.)&lt;/P&gt;
&lt;P&gt;An excellent way to test this is with Microsoft Word.&amp;nbsp; Word supports reconversion, and will show the candidates in the context menu when you right-click on a word.&lt;/P&gt;
&lt;H2&gt;Getting ITfFnReconversion&lt;/H2&gt;
&lt;P&gt;This is a two-step process.&amp;nbsp; First, you get the system function provider, and then you get the reconversion pointer (error checking is omitted):&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;ITfFunctionProvider* ipProvider;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;hr = ITfThreadMgr::GetFunctionProvider(GUID_SYSTEM_FUNCTIONPROVIDER, &amp;amp;ipProvider);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;IUnknown* ipConv;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;hr = ipProvider-&amp;gt;GetFunction(GUID_NULL, IID_ITfFnReconversion, &amp;amp;ipConv);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;ITfFnReconversion *ipConversion;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;hr&amp;nbsp;= ipConv-&amp;gt;QueryInterface(IID_ITfFnReconversion, &amp;amp;ipConversion);&lt;/FONT&gt;&lt;/P&gt;
&lt;H2&gt;What should QueryRange do?&lt;/H2&gt;
&lt;P&gt;&lt;A href="http://msdn2.microsoft.com/library/ms538973.aspx" mce_href="http://msdn2.microsoft.com/library/ms538973.aspx"&gt;ITfFnReconversion::QueryRange&lt;/A&gt; needs to modify the range to cover the entire range of text contained&amp;nbsp;by the&amp;nbsp;conversion token.&amp;nbsp; An example is useful here, as that last sentence didn't even make sense to me.&amp;nbsp; The Speech text service does correction by words, and all words must be part of a single recognition.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;Therefore, the Speech text services's implementation of QueryRange alters the range of text to contain entire words that are part of a single recognition.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;If the range starts in the middle of a word with recognition data, QueryRange shifts the start of the range to the start of a word.&amp;nbsp; If the range starts in text that doesn't have recognition data associated with it, it moves the start point to a point where it does have recognition data, or to the end of the initial range.&amp;nbsp; If it runs off the end, it sets pfConvertable to FALSE, and returns NULL.&lt;/P&gt;
&lt;P&gt;If it does find some recognition data for the start of the range, it adjusts the end of the range in the same manner.&lt;/P&gt;
&lt;P&gt;But wait, you say.&amp;nbsp; How can QueryRange do all that when it doesn't have an edit cookie?&amp;nbsp; Well, it gets one in the usual manner - it (say it with me) &lt;EM&gt;schedules an edit session&lt;/EM&gt; to do all that work.&amp;nbsp; OK, you say, how can I&amp;nbsp;get my data back from an&amp;nbsp;asynchronous edit session?&amp;nbsp; Well, you're in luck - you're &lt;EM&gt;guaranteed&lt;/EM&gt; to be able to schedule a &lt;STRONG&gt;synchronous&lt;/STRONG&gt; edit session from &lt;A href="http://msdn2.microsoft.com/library/ms538973.aspx" mce_href="http://msdn2.microsoft.com/library/ms538973.aspx"&gt;ITfFnReconversion::QueryRange&lt;/A&gt;.&amp;nbsp; &lt;/P&gt;
&lt;H2&gt;What should GetReconversion do?&lt;/H2&gt;
&lt;P&gt;&lt;A href="http://msdn2.microsoft.com/library/ms538972.aspx" mce_href="http://msdn2.microsoft.com/library/ms538972.aspx"&gt;ITfFnReconversion::GetReconversion&lt;/A&gt; needs to compute the candidates from a target range (that should be aligned with a conversion token).&amp;nbsp; Like QueryRange, most of the work will need to be done from an edit session, and also like QueryRange, you are guaranteed to be able to schedule a synchronous edit session from within GetReconversion.&amp;nbsp; How you go about computing the candidates is discussed in my next post.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=2878099" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/tsfaware/archive/tags/tsf/default.aspx">tsf</category><category domain="http://blogs.msdn.com/tsfaware/archive/tags/dictation/default.aspx">dictation</category><category domain="http://blogs.msdn.com/tsfaware/archive/tags/Text+Services/default.aspx">Text Services</category><category domain="http://blogs.msdn.com/tsfaware/archive/tags/Applications/default.aspx">Applications</category></item><item><title>TSF Application interfaces</title><link>http://blogs.msdn.com/tsfaware/archive/2007/04/27/tsf-application-interfaces.aspx</link><pubDate>Sat, 28 Apr 2007 01:36:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:2291853</guid><dc:creator>Eric Brown</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/tsfaware/comments/2291853.aspx</comments><wfw:commentRss>http://blogs.msdn.com/tsfaware/commentrss.aspx?PostID=2291853</wfw:commentRss><wfw:comment>http://blogs.msdn.com/tsfaware/rsscomments.aspx?PostID=2291853</wfw:comment><description>&lt;P&gt;The first stop on the TSF tour is the application interfaces.&amp;nbsp; These are implemented by applications or text controls.&lt;/P&gt;
&lt;P&gt;An application (or text control) must implement &lt;A href="http://msdn2.microsoft.com/en-us/library/ms538384.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms538384.aspx"&gt;ITextStoreACP&lt;/A&gt; to be considered ‘TSF-aware'.&amp;nbsp; It may choose to implement any of the other interfaces described in the table below.&amp;nbsp; I also describe how TSF obtains an instance of each interface. &lt;/P&gt;
&lt;TABLE class="" cellSpacing=0 cellPadding=0 width=643 border=1&gt;
&lt;THEAD&gt;
&lt;TR&gt;
&lt;TD class="" vAlign=top width=265&gt;
&lt;P&gt;&lt;B&gt;Interface&lt;/B&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" vAlign=top width=102&gt;
&lt;P&gt;&lt;B&gt;Optional?&lt;/B&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" vAlign=top width=276&gt;
&lt;P&gt;&lt;B&gt;How Obtained?&lt;/B&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/THEAD&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD class="" vAlign=top width=265&gt;
&lt;P&gt;&lt;A href="http://msdn2.microsoft.com/en-us/library/ms538384.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms538384.aspx"&gt;ITextStoreACP&lt;/A&gt; &lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" vAlign=top width=102&gt;
&lt;P&gt;No&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" vAlign=top width=276&gt;
&lt;P&gt;&lt;A&gt;Passed to &lt;/A&gt;&lt;A href="http://msdn2.microsoft.com/en-us/library/ms538890.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms538890.aspx"&gt;ITfDocumentMgr::CreateContext&lt;/A&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class="" vAlign=top width=265&gt;
&lt;P&gt;&lt;A href="http://msdn2.microsoft.com/en-us/library/ms628582.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms628582.aspx"&gt;ITfInputScope&lt;/A&gt; &lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" vAlign=top width=102&gt;
&lt;P&gt;Yes&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" vAlign=top width=276&gt;
&lt;P&gt;Returned from &lt;A href="http://msdn2.microsoft.com/en-us/library/ms538448.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms538448.aspx"&gt;ITextStoreACP::RequestSupportedAttrs&lt;/A&gt; with GUID_PROP_INPUTSCOPE.&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class="" vAlign=top width=265&gt;
&lt;P&gt;&lt;A href="http://msdn2.microsoft.com/en-us/library/aa382054.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/aa382054.aspx"&gt;ITfInputScope2&lt;/A&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" vAlign=top width=102&gt;
&lt;P&gt;Yes&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" vAlign=top width=276&gt;
&lt;P&gt;QI from &lt;A href="http://msdn2.microsoft.com/en-us/library/ms628582.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms628582.aspx"&gt;ITfInputScope&lt;/A&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class="" vAlign=top width=265&gt;
&lt;P&gt;&lt;A href="http://msdn2.microsoft.com/en-us/library/ms628877.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms628877.aspx"&gt;ITfPersistentPropertyLoaderACP&lt;/A&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" vAlign=top width=102&gt;
&lt;P&gt;Yes&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" vAlign=top width=276&gt;
&lt;P&gt;Passed to &lt;A href="http://msdn2.microsoft.com/en-us/library/ms538394.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms538394.aspx"&gt;ITextStoreACPServices::Unserialize&lt;/A&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class="" vAlign=top width=265&gt;
&lt;P&gt;&lt;A href="http://msdn2.microsoft.com/en-us/library/ms628799.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms628799.aspx"&gt;ITfMouseTrackerACP&lt;/A&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" vAlign=top width=102&gt;
&lt;P&gt;Yes&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" vAlign=top width=276&gt;
&lt;P&gt;QI from &lt;A href="http://msdn2.microsoft.com/en-us/library/ms538384.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms538384.aspx"&gt;ITextStoreACP&lt;/A&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class="" vAlign=top width=265&gt;
&lt;P&gt;&lt;A href="http://msdn2.microsoft.com/en-us/library/ms538740.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms538740.aspx"&gt;ITfContextOwnerCompositionSink&lt;/A&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" vAlign=top width=102&gt;
&lt;P&gt;Yes&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" vAlign=top width=276&gt;
&lt;P&gt;Passed to &lt;A href="http://msdn2.microsoft.com/en-us/library/ms538890.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms538890.aspx"&gt;ITfDocumentMgr::CreateContext&lt;/A&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class="" vAlign=top width=265&gt;
&lt;P&gt;&lt;A href="http://msdn2.microsoft.com/en-us/library/aa383201.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/aa383201.aspx"&gt;ITfUIElementSink&lt;/A&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" vAlign=top width=102&gt;
&lt;P&gt;Yes&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" vAlign=top width=276&gt;
&lt;P&gt;Passed to &lt;A href="http://msdn2.microsoft.com/en-us/library/ms628945.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms628945.aspx"&gt;ITfSource::AdviseSink&lt;/A&gt; (see below)&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P&gt;Note: I put &lt;A href="http://msdn2.microsoft.com/en-us/library/aa383201.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/aa383201.aspx"&gt;ITfUIElementSink&lt;/A&gt; here because text services &lt;I&gt;never&lt;/I&gt; implement this interface, even though it's an event sink (described in a future post). &amp;nbsp;&amp;nbsp;Full-screen applications (or games) would implement this interface if they wish to control the UI drawn by text services.&amp;nbsp; (See the discussion of &lt;A href="http://msdn2.microsoft.com/en-us/library/aa966970.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/aa966970.aspx"&gt;UILess mode&lt;/A&gt; in MSDN.)&lt;/P&gt;
&lt;TABLE class="" cellSpacing=0 cellPadding=0 width=631 border=1&gt;
&lt;THEAD&gt;
&lt;TR&gt;
&lt;TD class="" vAlign=top width=265&gt;
&lt;P&gt;&lt;B&gt;Interface&lt;/B&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" vAlign=top width=366&gt;
&lt;P&gt;&lt;B&gt;When to implement&lt;/B&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/THEAD&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD class="" vAlign=top width=265&gt;
&lt;P&gt;&lt;A href="http://msdn2.microsoft.com/en-us/library/ms538384.aspx"&gt;ITextStoreACP&lt;/A&gt; &lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" vAlign=top width=366&gt;
&lt;P&gt;Always implement this.&amp;nbsp; &lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class="" vAlign=top width=265&gt;
&lt;P&gt;&lt;A href="http://msdn2.microsoft.com/en-us/library/ms628582.aspx"&gt;ITfInputScope&lt;/A&gt; &lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" vAlign=top width=366&gt;
&lt;P&gt;Consider implementing this.&amp;nbsp; It's not hard, and some text services use it to improve recognition (e.g., Windows Speech Recognition knows about the URL input scope, and has special code for that).&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class="" vAlign=top width=265&gt;
&lt;P&gt;&lt;A href="http://msdn2.microsoft.com/en-us/library/aa382054.aspx"&gt;ITfInputScope2&lt;/A&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" vAlign=top width=366&gt;
&lt;P&gt;Implement this if you implemented &lt;A href="http://msdn2.microsoft.com/en-us/library/ms628582.aspx"&gt;ITfInputScope&lt;/A&gt;, and you need the extra functionality (string enumeration).&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class="" vAlign=top width=265&gt;
&lt;P&gt;&lt;A href="http://msdn2.microsoft.com/en-us/library/ms628877.aspx"&gt;ITfPersistentPropertyLoaderACP&lt;/A&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" vAlign=top width=366&gt;
&lt;P&gt;Implement this if you support asynchronous property loading.&amp;nbsp; If you don't know what that means, you don't need to implement this.&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class="" vAlign=top width=265&gt;
&lt;P&gt;&lt;A href="http://msdn2.microsoft.com/en-us/library/ms628799.aspx"&gt;ITfMouseTrackerACP&lt;/A&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" vAlign=top width=366&gt;
&lt;P&gt;Implement this to help handwriting recognition (I believe that you must implement this to get gestures).&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class="" vAlign=top width=265&gt;
&lt;P&gt;&lt;A href="http://msdn2.microsoft.com/en-us/library/ms538740.aspx"&gt;ITfContextOwnerCompositionSink&lt;/A&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" vAlign=top width=366&gt;
&lt;P&gt;Implement this if you need control over compositions.&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD class="" vAlign=top width=265&gt;
&lt;P&gt;&lt;A href="http://msdn2.microsoft.com/en-us/library/aa383201.aspx"&gt;ITfUIElementSink&lt;/A&gt;&lt;/P&gt;&lt;/TD&gt;
&lt;TD class="" vAlign=top width=366&gt;
&lt;P&gt;Only implement this if your application takes over the screen,&amp;nbsp;and you still want IMEs to work inside your application.&amp;nbsp; It's a fair amount of work to implement this.&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=2291853" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/tsfaware/archive/tags/tsf/default.aspx">tsf</category><category domain="http://blogs.msdn.com/tsfaware/archive/tags/tour/default.aspx">tour</category><category domain="http://blogs.msdn.com/tsfaware/archive/tags/Applications/default.aspx">Applications</category></item></channel></rss>