<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="https://www.w3.org/2005/Atom" xmlns:sy="https://purl.org/rss/1.0/modules/syndication/" xmlns:dc="https://purl.org/dc/elements/1.1/" xmlns:content="https://purl.org/rss/1.0/modules/content/" xmlns:wfw="https://wellformedweb.org/CommentAPI/" xmlns:slash="https://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>TSF Aware</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/tsfaware/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/tsfaware/feed.xml</link>
    <description>Dictation, Windows Speech Recognition, and Text Services Framework.</description>
    <lastBuildDate>Tue, 16 Apr 2019 05:34:40 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>DisplayUI and the Extra Data parameters</title>
      <link>https://docs.microsoft.com/archive/blogs/tsfaware/displayui-and-the-extra-data-parameters</link>
      <pubDate>Thu, 12 Sep 2013 10:53:19 GMT</pubDate>
      <dc:creator><![CDATA[Eric C Brown]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/tsfaware/2013/09/12/displayui-and-the-extra-data-parameters/</guid>
      <description><![CDATA[Hardcore SAPI programmers know that you can show the various SR engine user experiences (user...]]></description>
      <content:encoded><![CDATA[<p>Hardcore SAPI programmers know that you can show the various SR engine user experiences (user training, microphone training, <a href="https://msdn.microsoft.com/en-us/library/ee431897(v=vs.85).aspx">and so forth</a>) using <a href="https://msdn.microsoft.com/en-us/library/ee413270(v=vs.85).aspx">ISpRecognizer::DisplayUI</a>.&#160; (Even harder-core SAPI developers know that the <em>real</em> function is <a href="https://msdn.microsoft.com/en-us/library/ee450873(v=vs.85).aspx">ISpObjectToken::DisplayUI</a>, and that ISpRecognizer::DisplayUI simply forwards to the token of the loaded engine, but I digress…)</p>  <p>Most of the examples for DisplayUI just show the simple case where all the extra data parameters are NULL or 0, and don’t really explain what all those parameters are for.&#160; Mostly that’s because these parameters are vendor specific (i.e., different SR engines may have different behavior); the following behaviors are specifically for the Microsoft Desktop SR engine.&#160; Also, the valid values for the parameters depend on the pszTypeOfUI parameter.</p>  <p>For the Microsoft Desktop SR engine, the pUnkObject parameter should always be NULL.&#160; There are no (interesting) valid non-null values for this parameter.</p>  <p>pvExtraData and cbExtraData can be non-NULL if pszTypeOfUI is either <a href="https://msdn.microsoft.com/en-us/library/ee431894(v=vs.85).aspx">SPDUI_UserTraining</a> or <a href="https://msdn.microsoft.com/en-us/library/ee431886(v=vs.85).aspx">SPDUI_AddRemoveWord</a>.&#160; </p>  <p>When pszTypeOfUI is SPDUI_AddRemoveWord, then pvExtraData should be a standard null-terminated string containing the word to add to the lexicon.</p>  <p>When pszTypeOfUI is SPDUI_UserTraining, then pvExtraData should be a <a href="https://blogs.msdn.com/b/oldnewthing/archive/2009/10/08/9904646.aspx">double-null-terminated string</a> containing a set of training sentences.</p>  <p>Typically there should be 20-30 sentences to get good results.</p>]]></content:encoded>
    </item>
    <item>
      <title>The history of UI Automation</title>
      <link>https://docs.microsoft.com/archive/blogs/tsfaware/the-history-of-ui-automation</link>
      <pubDate>Wed, 10 Apr 2013 07:00:00 GMT</pubDate>
      <dc:creator><![CDATA[Eric C Brown]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/tsfaware/2013/04/10/the-history-of-ui-automation/</guid>
      <description><![CDATA[Raymond Chen wrote a post about retrieving the text under the cursor using UI Automation, and he had...]]></description>
      <content:encoded><![CDATA[<p>Raymond Chen wrote a <a href="https://blogs.msdn.com/b/oldnewthing/archive/2013/04/08/10409196.aspx">post</a> about retrieving the text under the cursor using UI Automation, and he had a comment that “Some people are under the mistaken impressions that UI Automation works only for extracting data from applications written in managed code.&#160; That is not true.”</p>  <p>Well, sort of.</p>  <p>UI Automation was first released with Windows Vista, and in Vista, the only UI Automation providers <em>were</em> in managed code.&#160; </p>  <p>During Windows 7, the Accessibility team ported the UI Automation providers to native code, and created a (bi-directional) “bridge” to Active Accessibility clients.&#160; (They also back-ported the native providers to Vista and released them as part of the Platform Update for Windows Vista.)</p>  <p>Even in Windows 7, however, the native UI Automation providers did not have <a href="https://msdn.microsoft.com/en-us/library/system.windows.automation.textpattern.aspx">TextPattern</a> support for edit controls and richedit controls.&#160; That was added in Windows 8.</p>]]></content:encoded>
    </item>
    <item>
      <title>Lexicons and Command Grammars</title>
      <link>https://docs.microsoft.com/archive/blogs/tsfaware/lexicons-and-command-grammars</link>
      <pubDate>Wed, 07 Mar 2012 23:16:00 GMT</pubDate>
      <dc:creator><![CDATA[Eric C Brown]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/tsfaware/2012/03/07/lexicons-and-command-grammars/</guid>
      <description><![CDATA[If you have a command grammar, and you need a word with an unusual pronunciation, you can use the...]]></description>
      <content:encoded><![CDATA[<p>If you have a command grammar, and you need a word with an unusual pronunciation, you can use the <a href="https://msdn.microsoft.com/en-us/library/ms723634(v=vs.85).aspx#tag_PHRASE">PRON attribute of the &lt;PHRASE&gt; tag</a> to specify a pronunciation using either a <a href="https://msdn.microsoft.com/en-us/library/ms717239(v=VS.85).aspx">phoneme representation</a> or an explicit array of PhoneIDs (phoneme identifiers) that you have extracted from the <a href="https://msdn.microsoft.com/en-us/library/ms717239(v=VS.85).aspx">SpPhoneConverter</a> (the SAPI default converter between phoneme symbols and phoneme IDs).</p>
<p>If you use the PRON attribute for a phrase, you will also want to use the DISP attribute as well to specify a display form, or else the textual representation of the phrase (in the SPPHRASE structure) and the text feedback will use the phoneme set.&nbsp;&nbsp;&nbsp; If you&rsquo;re not providing text feedback (and you&rsquo;re using an in-process recognizer), then this will not be a problem.</p>]]></content:encoded>
    </item>
    <item>
      <title>Training versus Lexicons</title>
      <link>https://docs.microsoft.com/archive/blogs/tsfaware/training-versus-lexicons</link>
      <pubDate>Tue, 06 Mar 2012 23:50:37 GMT</pubDate>
      <dc:creator><![CDATA[Eric C Brown]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/tsfaware/2012/03/06/training-versus-lexicons/</guid>
      <description><![CDATA[I’ve received a number of requests from people who want to train the recognizer from wave...]]></description>
      <content:encoded><![CDATA[<p>I’ve received a number of requests from people who want to train the recognizer from wave files.&#160; I’ve helped them, but one thing I’ve come to realize is that they’re confusing training with lexicons.</p>  <p>In particular, <b>training the engine will not add new words to the vocabulary. </b></p>  <p>Training the engine from a set of wave files is useful <i>only</i> if you wish to recognize more audio from other wave files <b>from the same speaker.</b>&#160; It’s not even terribly useful if you want to recognize <i>live</i> audio from the same speaker; the noise characteristics are often different, resulting in a different acoustic model.</p>  <p>If your problem is that you have a set of words that don’t exist in the default dictation vocabulary, then what you need to do is <a href="https://msdn.microsoft.com/en-us/library/ms717919(v=vs.85).aspx">create a lexicon</a>.</p>  <p>There are two kinds of lexicons that are interesting in this situation: User Lexicons, and Application lexicons.&#160; (Engine lexicons are also available, but can’t be modified.)</p>  <p>The difference is that User lexicons are specific to the user profile; whereas Application lexicons are shared across users and profiles.&#160; There is only one User lexicon per profile, but there can be an arbitrary number of Application lexicons.</p>  <p>Entries in the User lexicon override entries in the Application Lexicon, and entries in newer Application lexicons override entries in older Application lexicons.</p>  <p>Application lexicons are ‘write-once’ – that is, once the lexicon has been created, it cannot be modified.&#160; Typically, the application lexicon is created at application install time, and removed on uninstall.</p>  <p>Windows Speech Recognition has built-in wizards to manage the user lexicon (programmatically accessible via <a href="https://msdn.microsoft.com/en-us/library/ee125453(v=VS.85).aspx">ISpRecognizer::DisplayUI</a> or <a href="https://msdn.microsoft.com/en-us/library/ms719548(v=VS.85).aspx">ISpTokenUI::DisplayUI</a>; the TypeOfUI parameter should be <a href="https://msdn.microsoft.com/en-us/library/ee431897(v=vs.85).aspx">SPDUI_AddRemoveWord</a>).</p>  <p>I’ll go into more detail on the lexicon methods in my next post.</p>]]></content:encoded>
    </item>
    <item>
      <title>The Complete Metropolis</title>
      <link>https://docs.microsoft.com/archive/blogs/tsfaware/the-complete-metropolis</link>
      <pubDate>Mon, 03 May 2010 10:14:15 GMT</pubDate>
      <dc:creator><![CDATA[Eric C Brown]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/tsfaware/2010/05/03/the-complete-metropolis/</guid>
      <description><![CDATA[The most influential SF movie of all time (referenced and ripped off by everyone from Kubrick to...]]></description>
      <content:encoded><![CDATA[<div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:5737277B-5D6D-4f48-ABFC-DD9C333F4C5D:69edb0f0-13ea-43a2-b684-ee0da2644320" class="wlWriterEditableSmartContent"><div id="1e90408d-c519-4955-8cad-b00ded4f6d80" style="margin: 0px; padding: 0px; display: inline;"><div><a href="https://www.youtube.com/watch?v=n92VYq91zIw" target="_new"><img src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/BlogFileStorage/blogs_msdn/tsfaware/WindowsLiveWriter/TheCompleteMetropolis_8FF6/videoa379b601ef35.jpg" original-url="https://blogs.msdn.com/blogfiles/tsfaware/WindowsLiveWriter/TheCompleteMetropolis_8FF6/videoa379b601ef35.jpg" style="border-style: none" galleryimg="no" onload="var downlevelDiv = document.getElementById('1e90408d-c519-4955-8cad-b00ded4f6d80'); downlevelDiv.innerHTML = &quot;&lt;div&gt;&lt;object width=\&quot;425\&quot; height=\&quot;355\&quot;&gt;&lt;param name=\&quot;movie\&quot; value=\&quot;https://www.youtube.com/v/n92VYq91zIw&amp;hl=en\&quot;&gt;&lt;\/param&gt;&lt;embed src=\&quot;https://www.youtube.com/v/n92VYq91zIw&amp;hl=en\&quot; type=\&quot;application/x-shockwave-flash\&quot; width=\&quot;425\&quot; height=\&quot;355\&quot;&gt;&lt;\/embed&gt;&lt;\/object&gt;&lt;\/div&gt;&quot;;" alt=""></a></div></div></div>  <p>The most influential SF movie of all time (referenced and ripped off by everyone from Kubrick to Besson) is finally available in a complete edition.&#160; </p>  <p>Fritz Lang’s 1927 masterpiece has only been available in incomplete form (and for decades was only available in a heavily re-edited version).</p>  <p>Two years ago, curators at the Buenos Aires Museum of Film discovered a version of the film that ran 25 minutes longer than any other known print.</p>  <p>It has been restored and will be available on <a href="https://www.kino.com/metropolis/main.html">DVD and Blu-Ray in November</a>.</p>  <p>I can’t wait.</p>]]></content:encoded>
    </item>
    <item>
      <title>Detecting Sleep Mode in SAPI</title>
      <link>https://docs.microsoft.com/archive/blogs/tsfaware/detecting-sleep-mode-in-sapi</link>
      <pubDate>Mon, 22 Mar 2010 07:00:00 GMT</pubDate>
      <dc:creator><![CDATA[Eric C Brown]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/tsfaware/2010/03/22/detecting-sleep-mode-in-sapi/</guid>
      <description><![CDATA[If you’ve done any development with the shared recognizer, you’ve probably had problems determining...]]></description>
      <content:encoded><![CDATA[<p>If you’ve done any development with the shared recognizer, you’ve probably had problems determining when the shared recognizer is in sleep mode.</p>  <p>Determining when the shared recognizer is OFF is easy enough; <a href="https://msdn.microsoft.com/en-us/library/ee413277(VS.85).aspx">ISpRecognizer::GetRecoState</a> will return SPRST_INACTIVE.</p>  <p>But figuring out the sleep state is much harder.&#160; That’s because the shared recognizer is active (SPRST_ACTIVE_ALWAYS), but it’s not listening for all commands.</p>  <p>In Windows 7, there is a new interface that expose ‘categories’ (<a href="https://msdn.microsoft.com/en-us/library/ee413265(VS.85).aspx">ISpRecognizer3</a>).&#160; </p>  <p>When WSR is sleeping, <a href="https://msdn.microsoft.com/en-us/library/ee413266(VS.85).aspx">ISpRecognizer3::GetActiveCategory</a> will return a non-null <a href="https://msdn.microsoft.com/en-us/library/ee413235(VS.85).aspx">ISpRecoCategory</a> of type <a href="https://msdn.microsoft.com/en-us/library/ee431836(VS.85).aspx">SPCT_SLEEP</a>.&#160; </p>  <p>When WSR is listening, <a href="https://msdn.microsoft.com/en-us/library/ee413266(VS.85).aspx">ISpRecognizer3::GetActiveCategory</a> will return a null <a href="https://msdn.microsoft.com/en-us/library/ee413235(VS.85).aspx">ISpRecoCategory</a>.&#160; </p>  <p>NOTE WELL:&#160; This is only guaranteed to work on Windows 7.&#160; It is not guaranteed to work on future versions of Windows.</p>  <p>Some sample code to get an ISpRecognizer3 interface from a shared recognizer stored in m_cpReco:</p>  <p>   <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:6b6d7b08-e9a1-43a5-a3d4-44ece20932ef" class="wlWriterEditableSmartContent"> <div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"> <div style="background: #000080; color: #fff; font-family: Verdana, Tahoma, Arial, sans-serif; font-weight: bold; padding: 2px 5px">ISpRecognizer3 snippet</div> <div style="background: #ddd; max-height: 500px; overflow: auto"> <ol style="background: #ffffff; margin: 0 0 0 2.5em; padding: 0 0 0 5px; white-space: nowrap"> <li>CComPtr&lt;ISpRecognizer3&gt; cpReco3;</li> <li style="background: #f3f3f3">hr = m_cpReco.QueryInterface&lt;ISpRecognizer3&gt;(&amp;cpReco3);</li> <li><span style="color:#0000ff">if</span> (SUCCEEDED(hr))</li> <li style="background: #f3f3f3">{</li> <li>    CComPtr&lt;ISpRecoCategory&gt; cpCategory;</li> <li style="background: #f3f3f3">    hr = cpReco3-&gt;GetActiveCategory(&amp;cpCategory);</li> <li>    <span style="color:#0000ff">if</span> (SUCCEEDED(hr) &amp;&amp; cpCategory != NULL)</li> <li style="background: #f3f3f3">    {</li> <li>        SPCATEGORYTYPE spct;</li> <li style="background: #f3f3f3">        hr = cpCategory-&gt;GetType(&amp;spct);</li> <li>        <span style="color:#0000ff">if</span> (SUCCEEDED(hr)</li> <li style="background: #f3f3f3">        {</li> <li>            fIsSleeping = spct = SPCT_SLEEP;</li> <li style="background: #f3f3f3">        }</li> <li>    }</li> <li style="background: #f3f3f3">}</li> </ol> </div> </div> </div> </p>  <p>In order to make this work, you’ll need to have the <a href="https://www.microsoft.com/downloads/details.aspx?FamilyID=c17ba869-9671-4330-a63e-1fd44e0e2505&amp;displaylang=en">Windows 7 SDK</a> installed and set as default in Visual Studio.</p>  <p>Also, you’ll need to make sure that you have the following version numbers defined (typically in targetver.h):</p>  <p><font size="2" face="Courier New">#define WINVER 0x0601</font></p>  <p><font size="2" face="Courier New">#define _WIN32_WINNT 0x0601</font></p>  <p>This will enable the Windows-7 only interfaces like ISpRecognizer3.</p>]]></content:encoded>
    </item>
    <item>
      <title>How to train the SAPI recognizer</title>
      <link>https://docs.microsoft.com/archive/blogs/tsfaware/how-to-train-the-sapi-recognizer</link>
      <pubDate>Mon, 15 Mar 2010 11:59:00 GMT</pubDate>
      <dc:creator><![CDATA[Eric C Brown]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/tsfaware/2010/03/15/how-to-train-the-sapi-recognizer/</guid>
      <description><![CDATA[Implementing SAPI training is relatively hard, and the documentation doesn’t really tell you what...]]></description>
      <content:encoded><![CDATA[<P>Implementing SAPI training is relatively hard, and the documentation doesn’t really tell you what you need to know. </P>
<P><A href="https://msdn.microsoft.com/en-us/library/ms718576(VS.85).aspx" mce_href="https://msdn.microsoft.com/en-us/library/ms718576(VS.85).aspx">ISpRecognizer2::SetTrainingState</A> switches the recognizer into or out of training mode. </P>
<P>When you go into training mode, all that really happens is that the recognizer gives the user a lot more leeway about recognitions.&nbsp; So if you’re trying to recognize a phrase, the engine will be a lot less strict about the recognition.</P>
<P>The engine doesn’t really do any adaptation until you <EM>leave</EM> training mode, and you have set the fAdaptFromTrainingData flag.</P>
<P>When the engine adapts, it scans the training audio stored under the profile data.&nbsp; It’s the training code’s responsibility to put new audio files where the engine can find it for adaptation.</P>
<P>These files also have to be labeled, so that the engine knows what was said.</P>
<P>So how do you do this?&nbsp; You need to use three of lesser-known SAPI APIs.&nbsp; In particular, you need to get the profile token using <A href="https://msdn.microsoft.com/en-us/library/ms718612(VS.85).aspx" mce_href="https://msdn.microsoft.com/en-us/library/ms718612(VS.85).aspx">ISpRecognizer::GetObjectToken</A>, and&nbsp; <A href="https://msdn.microsoft.com/en-us/library/ms718252(VS.85).aspx" mce_href="https://msdn.microsoft.com/en-us/library/ms718252(VS.85).aspx">SpObjectToken::GetStorageFileName</A> to properly locate the file.</P>
<P>Finally, you also need to use <A href="https://msdn.microsoft.com/en-us/library/ms719553(VS.85).aspx" mce_href="https://msdn.microsoft.com/en-us/library/ms719553(VS.85).aspx">ISpTranscript</A> to generate properly labeled audio files.</P>
<P>To put it all together, you need to do the following (pseudo-code):</P>
<P>Create an inproc recognizer &amp; bind the appropriate audio input.</P>
<P>Ensure that you’re retaining the audio for your recognitions; you’ll need it later.</P>
<P>Create a grammar containing the text to train.</P>
<P>Set the grammar’s state to pause the recognizer when a recognition occurs.&nbsp; (This helps with training from an audio file, as well.)</P>
<P>When a recognition occurs:</P>
<P>Get the recognized text and the retained audio (using <A href="https://msdn.microsoft.com/en-us/library/ee413319(VS.85).aspx" mce_href="https://msdn.microsoft.com/en-us/library/ee413319(VS.85).aspx">ISpRecoResult::GetAudio</A>).</P>
<P>QI the audio for IStream.</P>
<P>Create a stream object using CoCreateInstance(<A href="https://msdn.microsoft.com/en-us/library/ee431819(VS.85).aspx" mce_href="https://msdn.microsoft.com/en-us/library/ee431819(VS.85).aspx">CLSID_SpStream</A>).</P>
<P>Create a training audio file using <A href="https://msdn.microsoft.com/en-us/library/ms718612(VS.85).aspx" mce_href="https://msdn.microsoft.com/en-us/library/ms718612(VS.85).aspx">ISpRecognizer::GetObjectToken</A> and <A href="https://msdn.microsoft.com/en-us/library/ms718252(VS.85).aspx" mce_href="https://msdn.microsoft.com/en-us/library/ms718252(VS.85).aspx">ISpObjectToken::GetStorageFileName</A>, and bind it to the stream (using <A href="https://msdn.microsoft.com/en-us/library/ee413430(VS.85).aspx" mce_href="https://msdn.microsoft.com/en-us/library/ee413430(VS.85).aspx">ISpStreamFormat::GetFormat</A> and&nbsp;<A href="https://msdn.microsoft.com/en-us/library/ms719484(VS.85).aspx" mce_href="https://msdn.microsoft.com/en-us/library/ms719484(VS.85).aspx">ISpStream::BindToFile</A>).</P>
<P>Copy the retained audio into the stream object (using <A href="https://msdn.microsoft.com/en-us/library/aa380038(VS.85).aspx" mce_href="https://msdn.microsoft.com/en-us/library/aa380038(VS.85).aspx">IStream::CopyTo</A>) .</P>
<P>QI the stream object for the <A href="https://msdn.microsoft.com/en-us/library/ms719553(VS.85).aspx" mce_href="https://msdn.microsoft.com/en-us/library/ms719553(VS.85).aspx">ISpTranscript</A> interface, and use <A href="https://msdn.microsoft.com/en-us/library/ms719554(VS.85).aspx" mce_href="https://msdn.microsoft.com/en-us/library/ms719554(VS.85).aspx">ISpTranscript::AppendTranscript</A> to add the recognized text to the stream.</P>
<P>Close the stream, update the grammar for the next utterance, resume the recognizer, and repeat until you’re out of training text.</P>]]></content:encoded>
    </item>
    <item>
      <title>That pesky terminating composition</title>
      <link>https://docs.microsoft.com/archive/blogs/tsfaware/that-pesky-terminating-composition</link>
      <pubDate>Mon, 08 Mar 2010 07:00:00 GMT</pubDate>
      <dc:creator><![CDATA[Eric C Brown]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/tsfaware/2010/03/08/that-pesky-terminating-composition/</guid>
      <description><![CDATA[If you’re developing a text service for Windows XP, you’ve likely found that your composition gets...]]></description>
      <content:encoded><![CDATA[<p>If you’re developing a text service for Windows XP, you’ve likely found that your composition gets terminated unexpectedly whenever you have more than one character.&#160; On English, you can avoid terminating your composition by making sure that every character in the composition has the GUID_PROP_COMPOSING property associated with it, by making sure that you call <a href="https://blogs.msdn.com/tsfaware/archive/2009/05/15/why-you-need-to-actually-test-instead-of-just-looking-at-the-source-code.aspx">ITfComposition::ShiftStart and/or ITfComposition::ShiftEnd</a> appropriately.</p>  <p>However, with some languages, even this will not prevent your compositions from being terminated.</p>  <p>I had a chat with the TSF developers, and they said:</p>  <blockquote>   <p>This was sort of by design on XP to terminate non-EA compositions by default. The design changed in Vista, but the change wasn’t ported to XP because it went as a new feature, not as a bug fix. </p> </blockquote>  <p>The good news is that there’s a workaround for XP: your text service needs to add\set this value in the registry:</p>  <p>HKCU\SOFTWARE\Microsoft\CTF\CUAS\NonEAComposition=2</p>  <p>(2 means ‘enable’, all others or no entry – non-EA compositions will be disabled).</p>  <p>Hopefully others will find this useful.</p>]]></content:encoded>
    </item>
    <item>
      <title>Specifying parameters for an inproc Recognizer</title>
      <link>https://docs.microsoft.com/archive/blogs/tsfaware/specifying-parameters-for-an-inproc-recognizer</link>
      <pubDate>Mon, 01 Mar 2010 07:00:00 GMT</pubDate>
      <dc:creator><![CDATA[Eric C Brown]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/tsfaware/2010/03/01/specifying-parameters-for-an-inproc-recognizer/</guid>
      <description><![CDATA[I’ve seen a couple of questions come by the listen alias about using an in-process speech...]]></description>
      <content:encoded><![CDATA[<p>I’ve seen a couple of questions come by the listen alias about using an in-process speech recognizer.&#160; When you use an in-process recognizer, you have to specify a lot more than you need to specify with the shared recognizer.</p>  <p>In particular, you need to specify an audio source <strong>and</strong> a recognition engine.&#160; The shared recognizer uses the defaults for both of these.</p>  <p>Most people figure out that they need to specify an audio source; more commonly (and I’ve tripped over this myself) they forget to specify a recognition engine.</p>  <p>And while there’s a nifty helper for the audio input in sphelper.h (namely, SpGetDefaultTokenFromCategoryId(SPCAT_AUDIOIN, &amp;cpToken)), there isn’t a helper for the recognition engine.</p>  <p>So, here’s a helper function that returns the object token for the default shared recognizer:</p>  <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:9ce6104f-a9aa-4a17-a79f-3a39532ebf7c:8faebf76-343d-4d15-a0a9-86998e874fbf" class="wlWriterEditableSmartContent"> <div style="border: #000080 1px solid; color: #000; font-family: 'Courier New', Courier, Monospace; font-size: 10pt"> <div style="background: #fff; max-height: 500px; overflow: auto"> <ol style="background: #ffffff; margin: 0; padding: 0 0 0 5px; white-space: nowrap"> <li><span style="color:#008000">// Get the object token for the default shared recognizer engine.</span></li> <li style="background: #f3f3f3">HRESULT SpGetDefaultSharedRecognizerToken(ISpObjectToken **ppSharedRecognizerToken)</li> <li>{</li> <li style="background: #f3f3f3">    HRESULT hr = S_OK;</li> <li>    <span style="color:#0000ff">const</span> WCHAR pszWindowsCompatAtt[] = L<span style="color:#a31515">&quot;windowsV6compatible&quot;</span>;</li> <li style="background: #f3f3f3">    LANGID UIlangID = GetUserDefaultUILanguage();</li> <li>    </li> <li style="background: #f3f3f3">    <span style="color:#008000">// Find recognizers that match windowsV6compatible and the primary language id of the UI.</span></li> <li>    <span style="color:#008000">// Use primary language because there may be several recognizers available for different sub-languages,</span></li> <li style="background: #f3f3f3">    <span style="color:#008000">// and there is generally only one UI language per primary language.</span></li> <li>    <span style="color:#008000">// e.g. US and UK English recognizers on a US English system.</span></li> <li style="background: #f3f3f3">    <span style="color:#008000">// If so, to distinguish these the locale is used below.</span></li> <li>&nbsp;</li> <li style="background: #f3f3f3">    CComPtr&lt;IEnumSpObjectTokens&gt; cpEnum;</li> <li>    hr = SpEnumTokensMatchingPrimaryLangID(SPCAT_RECOGNIZERS, PRIMARYLANGID(UIlangID), pszWindowsCompatAtt, &amp;cpEnum);</li> <li style="background: #f3f3f3">&nbsp;</li> <li>    ULONG ulRecognizers(0);</li> <li style="background: #f3f3f3">    <span style="color:#0000ff">if</span> (SUCCEEDED(hr))</li> <li>    {</li> <li style="background: #f3f3f3">        hr = cpEnum-&gt;GetCount(&amp;ulRecognizers);</li> <li>    }</li> <li style="background: #f3f3f3">&nbsp;</li> <li>    <span style="color:#0000ff">if</span> (SUCCEEDED(hr))</li> <li style="background: #f3f3f3">    {</li> <li>        <span style="color:#0000ff">if</span> (ulRecognizers == 0)</li> <li style="background: #f3f3f3">        {</li> <li>            <span style="color:#008000">// If zero - error.</span></li> <li style="background: #f3f3f3">            hr = SPERR_RECOGNIZER_NOT_FOUND;</li> <li>        }</li> <li style="background: #f3f3f3">        <span style="color:#0000ff">else</span> <span style="color:#0000ff">if</span> (ulRecognizers == 1)</li> <li>        {</li> <li style="background: #f3f3f3">            <span style="color:#008000">// If one - we are done.</span></li> <li>            hr = cpEnum-&gt;Item(0, ppSharedRecognizerToken);</li> <li style="background: #f3f3f3">        }</li> <li>        <span style="color:#0000ff">else</span></li> <li style="background: #f3f3f3">        {</li> <li>            <span style="color:#008000">// More than one recognizer matches - we must pick the best default:</span></li> <li style="background: #f3f3f3">            BOOL fFoundDefault = FALSE;</li> <li>&nbsp;</li> <li style="background: #f3f3f3">            <span style="color:#008000">// If there&#39;s no language-specific default then use the locale.</span></li> <li>            LANGID localeID = GetUserDefaultLangID();</li> <li style="background: #f3f3f3">            <span style="color:#0000ff">if</span> (!fFoundDefault &amp;&amp; SUCCEEDED(hr) &amp;&amp;</li> <li>                PRIMARYLANGID(UIlangID) == PRIMARYLANGID(localeID))</li> <li style="background: #f3f3f3">            {</li> <li>                <span style="color:#008000">// First see if there&#39;s an engine whose language exactly matches the locale.</span></li> <li style="background: #f3f3f3">                <span style="color:#008000">// For example if the langid is U.S English, but the locale is U.K. English</span></li> <li>                <span style="color:#008000">// and there&#39;s a U.K. recognizer then use that.</span></li> <li style="background: #f3f3f3">&nbsp;</li> <li>                hr = S_OK;</li> <li style="background: #f3f3f3">                WCHAR pszLocaleString[] = L<span style="color:#a31515">&quot;Language=XXXXXXXX&quot;</span>;</li> <li>                SpHexFromUlong(pszLocaleString + wcslen(pszLocaleString) - 8, localeID);</li> <li style="background: #f3f3f3">                <span style="color:#0000ff">for</span> (ULONG ul = 0; SUCCEEDED(hr) &amp;&amp; ul &lt; ulRecognizers; ul++)</li> <li>                {</li> <li style="background: #f3f3f3">                    CComPtr&lt;ISpObjectToken&gt; cpToken;</li> <li>                    hr = cpEnum-&gt;Item(ul, &amp;cpToken);</li> <li style="background: #f3f3f3">                    <span style="color:#0000ff">if</span> (SUCCEEDED(hr))</li> <li>                    {</li> <li style="background: #f3f3f3">                        hr = cpToken-&gt;MatchesAttributes(pszLocaleString, &amp;fFoundDefault);</li> <li>                    }</li> <li style="background: #f3f3f3">&nbsp;</li> <li>                    <span style="color:#0000ff">if</span> (SUCCEEDED(hr) &amp;&amp; fFoundDefault)</li> <li style="background: #f3f3f3">                    {</li> <li>                        *ppSharedRecognizerToken = cpToken.Detach();</li> <li style="background: #f3f3f3">                        <span style="color:#0000ff">break</span>;</li> <li>                    }</li> <li style="background: #f3f3f3">                }</li> <li>            }</li> <li style="background: #f3f3f3">&nbsp;</li> <li>            <span style="color:#008000">// If there&#39;s no engine that directly matches the locale see if the backup list of SupportedLocales is matched.</span></li> <li style="background: #f3f3f3">            <span style="color:#0000ff">if</span> (!fFoundDefault &amp;&amp; (SUCCEEDED(hr) || hr == SPERR_NOT_FOUND) &amp;&amp;</li> <li>                PRIMARYLANGID(UIlangID) == PRIMARYLANGID(localeID))</li> <li style="background: #f3f3f3">            {</li> <li>                <span style="color:#008000">// See if there&#39;s an engine which has a supported Locale matches the current locale.</span></li> <li style="background: #f3f3f3">                <span style="color:#008000">// For example if the langid is U.S English, but the locale is Australian English</span></li> <li>                <span style="color:#008000">// there may be no recognizer that directly supports Australian English, </span></li> <li style="background: #f3f3f3">                <span style="color:#008000">// but a U.K. recognizer might specify it can be used in the Australian English locale with this attribute.</span></li> <li>&nbsp;</li> <li style="background: #f3f3f3">                hr = S_OK;</li> <li>                WCHAR pszSupportedLocalesString[] = L<span style="color:#a31515">&quot;SupportedLocales=XXXXXXXX&quot;</span>;</li> <li style="background: #f3f3f3">                SpHexFromUlong(pszSupportedLocalesString + wcslen(pszSupportedLocalesString) - 8, localeID);</li> <li>                <span style="color:#0000ff">for</span> (ULONG ul = 0; SUCCEEDED(hr) &amp;&amp; ul &lt; ulRecognizers; ul++)</li> <li style="background: #f3f3f3">                {</li> <li>                    CComPtr&lt;ISpObjectToken&gt; cpToken;</li> <li style="background: #f3f3f3">                    hr = cpEnum-&gt;Item(ul, &amp;cpToken);</li> <li>                    <span style="color:#0000ff">if</span> (SUCCEEDED(hr))</li> <li style="background: #f3f3f3">                    {</li> <li>                        hr = cpToken-&gt;MatchesAttributes(pszSupportedLocalesString, &amp;fFoundDefault);</li> <li style="background: #f3f3f3">                    }</li> <li>&nbsp;</li> <li style="background: #f3f3f3">                    <span style="color:#0000ff">if</span> (SUCCEEDED(hr) &amp;&amp; fFoundDefault)</li> <li>                    {</li> <li style="background: #f3f3f3">                        *ppSharedRecognizerToken = cpToken.Detach();</li> <li>                        <span style="color:#0000ff">break</span>;</li> <li style="background: #f3f3f3">                    }</li> <li>                }</li> <li style="background: #f3f3f3">            }</li> <li>&nbsp;</li> <li style="background: #f3f3f3">            <span style="color:#008000">// We still haven&#39;t found a match - just pick the first recognizer.</span></li> <li>            <span style="color:#0000ff">if</span> (!fFoundDefault &amp;&amp; (SUCCEEDED(hr) || hr == SPERR_NOT_FOUND))</li> <li style="background: #f3f3f3">            {</li> <li>                CComPtr&lt;ISpObjectToken&gt; cpToken;</li> <li style="background: #f3f3f3">                hr = cpEnum-&gt;Item(0, ppSharedRecognizerToken);</li> <li>            }</li> <li style="background: #f3f3f3">        }</li> <li>    }</li> <li style="background: #f3f3f3">&nbsp;</li> <li>    <span style="color:#0000ff">return</span> hr;</li> <li style="background: #f3f3f3">}</li> <li>&nbsp;</li> <li style="background: #f3f3f3">&nbsp;</li> <li><span style="color:#008000">// Return a token enumerator containing all tokens that match the primary language</span></li> <li style="background: #f3f3f3"><span style="color:#008000">// of a particular language id. pszRequiredAttributes can be used to specify additional attributes all tokens must have.</span></li> <li>HRESULT SpEnumTokensMatchingPrimaryLangID(<span style="color:#0000ff">const</span> LPCWSTR pszCategoryId, LANGID priLangID, LPCWSTR pszRequiredAtts,</li> <li style="background: #f3f3f3">                                                 IEnumSpObjectTokens **ppEnum)</li> <li>{</li> <li style="background: #f3f3f3">    HRESULT hr = S_OK;</li> <li>&nbsp;</li> <li style="background: #f3f3f3">    <span style="color:#008000">// First enumerate the tokens using pszRequiredAtts.</span></li> <li>    CComPtr&lt;ISpObjectTokenCategory&gt; cpCategory;</li> <li style="background: #f3f3f3">    hr = SpGetCategoryFromId(pszCategoryId, &amp;cpCategory);</li> <li>    </li> <li style="background: #f3f3f3">    CComPtr&lt;IEnumSpObjectTokens&gt; cpEnum;</li> <li>    <span style="color:#0000ff">if</span> (SUCCEEDED(hr))</li> <li style="background: #f3f3f3">    {</li> <li>        hr = cpCategory-&gt;EnumTokens(pszRequiredAtts, NULL, &amp;cpEnum);</li> <li style="background: #f3f3f3">    }</li> <li>&nbsp;</li> <li style="background: #f3f3f3">    ULONG ulTokens(0);</li> <li>    <span style="color:#0000ff">if</span> (SUCCEEDED(hr))</li> <li style="background: #f3f3f3">    {</li> <li>        hr = cpEnum-&gt;GetCount(&amp;ulTokens);</li> <li style="background: #f3f3f3">    }</li> <li>&nbsp;</li> <li style="background: #f3f3f3">    <span style="color:#008000">// Create enumerator to store new tokens.</span></li> <li>    CComPtr&lt;ISpObjectTokenEnumBuilder&gt; cpBuilder;</li> <li style="background: #f3f3f3">    <span style="color:#0000ff">if</span> (SUCCEEDED(hr))</li> <li>    {</li> <li style="background: #f3f3f3">        hr = cpBuilder.CoCreateInstance(CLSID_SpObjectTokenEnum);</li> <li>    }</li> <li style="background: #f3f3f3">    <span style="color:#0000ff">if</span> (SUCCEEDED(hr))</li> <li>    {</li> <li style="background: #f3f3f3">        hr = cpBuilder-&gt;SetAttribs(NULL, NULL);</li> <li>    }</li> <li style="background: #f3f3f3">&nbsp;</li> <li>    <span style="color:#008000">// Now, for each token, check language string to see if it matches.</span></li> <li style="background: #f3f3f3">    <span style="color:#0000ff">for</span> (ULONG ul = 0; SUCCEEDED(hr) &amp;&amp; ul &lt; ulTokens; ul++)</li> <li>    {</li> <li style="background: #f3f3f3">        LANGID tokenLangID(0);</li> <li>        CComPtr&lt;ISpObjectToken&gt; cpToken;</li> <li style="background: #f3f3f3">        hr = cpEnum-&gt;Item(ul, &amp;cpToken);</li> <li>        <span style="color:#0000ff">if</span> (SUCCEEDED(hr))</li> <li style="background: #f3f3f3">        {</li> <li>            <span style="color:#008000">// Just look at the first language id</span></li> <li style="background: #f3f3f3">            hr = SpGetLanguageFromToken(cpToken, &amp;tokenLangID);</li> <li>        }</li> <li style="background: #f3f3f3">&nbsp;</li> <li>        <span style="color:#0000ff">if</span> (SUCCEEDED(hr) &amp;&amp; PRIMARYLANGID(tokenLangID) == PRIMARYLANGID(priLangID))</li> <li style="background: #f3f3f3">        {</li> <li>            <span style="color:#008000">// Add to builder</span></li> <li style="background: #f3f3f3">            hr = cpBuilder-&gt;AddTokens(1, &amp;(cpToken.p));</li> <li>        }</li> <li style="background: #f3f3f3">    }</li> <li>&nbsp;</li> <li style="background: #f3f3f3">    <span style="color:#0000ff">if</span> (SUCCEEDED(hr))</li> <li>    {</li> <li style="background: #f3f3f3">        hr = cpBuilder-&gt;Reset();</li> <li>    }</li> <li style="background: #f3f3f3">    <span style="color:#0000ff">if</span> (SUCCEEDED(hr))</li> <li>    {</li> <li style="background: #f3f3f3">        *ppEnum = cpBuilder.Detach();</li> <li>    }</li> <li style="background: #f3f3f3">&nbsp;</li> <li>    <span style="color:#0000ff">return</span> hr;</li> <li style="background: #f3f3f3">}</li> </ol> </div> </div> </div>]]></content:encoded>
    </item>
    <item>
      <title>Finding out when WSR shows a window (or, a concise guide to IUIAutomationRegistrar)</title>
      <link>https://docs.microsoft.com/archive/blogs/tsfaware/finding-out-when-wsr-shows-a-window-or-a-concise-guide-to-iuiautomationregistrar</link>
      <pubDate>Tue, 25 Aug 2009 14:53:30 GMT</pubDate>
      <dc:creator><![CDATA[Eric C Brown]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/tsfaware/2009/08/25/finding-out-when-wsr-shows-a-window-or-a-concise-guide-to-iuiautomationregistrar/</guid>
      <description><![CDATA[When WSR shows a window (for example, the alternates dialog, the Disambiguation Numbers UI, or the...]]></description>
      <content:encoded><![CDATA[<p>When WSR shows a window (for example, the alternates dialog, the Disambiguation Numbers UI, or the dictation scratchpad), that window does not take focus.&#160; </p>  <p>These windows do not take focus because these windows could alter the state of the application that WSR is talking to.&#160; For example, if you’re renaming a file in Windows Explorer, when the focus goes away, the file gets renamed.</p>  <p>Unfortunately, though, accessibility applications often have problems finding these windows, even though these windows fire the standard WinEvents (several types of windows are plain dialogs, for example).</p>  <p>In Windows 7, WSR fires a custom UI Automation event when it shows or hides one of its custom windows (Disambiguation Numbers, dictation scratchpad, Alternates, Spelling, Pronunciation, Switch Windows, or Launch Application).</p>  <p>To do this, WSR uses the <a href="https://msdn.microsoft.com/en-us/library/dd388290(VS.85).aspx">IUIAutomationRegistrar</a> interface.</p>  <p><a href="https://msdn.microsoft.com/en-us/library/dd388291(VS.85).aspx">IUIAutomationRegistrar::RegisterEvent</a> defines a new event ID given a GUID and a name.&#160; If multiple applications register an event using the same GUID and name, they all get the same event ID.&#160; The event ID can also be used in a call to <a href="https://msdn.microsoft.com/en-us/library/dd373640(VS.85).aspx">SetWinEventHook</a>, if your application is using WinEvents.</p>  <p><strong>Beware</strong>: all registrations are <em>invalidated</em> when you release the IUIAutomationRegistrar interface pointer!&#160; So you <strong>must</strong> retain the interface pointer until you no longer wish to process events.&#160; (MSDN doesn’t make this clear.)</p>  <p>So, if you want to find out when WSR is showing one of its custom windows, call <a href="https://msdn.microsoft.com/en-us/library/dd388291(VS.85).aspx">IUIAutomationRegistrar::RegisterEvent</a> with these two event declarations, and check for these events in your event processing code.</p>  <p>const GUID GUID_ShowEvent = {&#160; <br />&#160;&#160;&#160; 0x3891149e, 0x7190, 0x47d0, {0xa5, 0x18, 0xca, 0x1c, 0xdb, 0x40, 0xf7, 0xe3}    <br />&#160; };    <br />#define UI_SHOW&#160;&#160;&#160;&#160;&#160; L&quot;Microsoft.Speech.UI.Shown&quot; </p>  <p>const GUID GUID_HideEvent = {&#160; <br />&#160;&#160;&#160; 0x987a1c35, 0x597b, 0x4947, {0x9e, 0xf8, 0xe7, 0xa6, 0x81, 0x42, 0xfd, 0x11}    <br />&#160; };    <br />#define UI_HIDDEN&#160;&#160;&#160; L&quot;Microsoft.Speech.UI.Hidden&quot;</p>]]></content:encoded>
    </item>
  </channel>
</rss>