Click here to Skip to main content
Licence CPOL
First Posted 21 Apr 2008
Views 13,817
Downloads 165
Bookmarked 24 times

Making Your Browser Talk

By | 21 Apr 2008 | Article
Use the Speech SDK to make Internet Explorer read documents or portions of documents to the user.
1_small.JPG

2.jpg

Requirements

  • Microsoft Speech SDK 5.1

http://msdn2.microsoft.com/en-us/library/bb250489.aspx (Building a BHO with VS2005) and
http://msdn2.microsoft.com/en-us/library/bb735853(VS.85).aspx#IEAddOnsMenus_topic2 (Creating Menus for IE) are two websites that I used for creating this addon. I will skip how to create a browser helper object and add it to the Internet Explorer Tools Menu and get straight to the interesting stuff. Most of the code to actually speak inside speakThread comes from the MSDN documentation on the Speech API.

The Speech Thread

#include <sapi.h >//we need this
...
DWORD WINAPI speakThread(LPVOID bstr)
{
    if (FAILED(::CoInitialize(NULL)))
        return -1;
    ISpVoice * pVoice = NULL;
    HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, 
                                 (void **)&pVoice);
    if( SUCCEEDED( hr ) )
    {
        hr = pVoice->Speak((BSTR)bstr,0,NULL);
        pVoice->WaitUntilDone(INFINITE);
        pVoice->Release();
        pVoice = NULL;
        ::CoUninitialize();
        return hr;
    }
    ::CoUninitialize();
    return hr;
}

What is happening here is that we are passing the thread a BSTR as an LPVOID. We initialize COM and create an interface of type ISpVoice. We call the Speak routine for this interface and give it the string we received. Next we wait until the routine is done before cleaning up.

STDMETHODIMP CCIESpeechBHO::Exec(const GUID *pguidCmdGroup, 
  DWORD nCmdID, DWORD nCmdExecOpt, 
  VARIANTARG *pvaIn, VARIANTARG *pvaOut) {

    CComPtr<idispatch /> spDoc;
    HRESULT hr  = m_pBrowser->get_Document(&spDoc);

    if(SUCCEEDED(hr))
    {
        CComQIPtr<ihtmldocument2 /> spHTMLDoc = spDoc;

        if(NULL != spHTMLDoc)
        {
            IHTMLElement* pHtmlElement = NULL;
            IHTMLSelectionObject* pHtmlSelectionObject;
            spHTMLDoc->get_selection(&pHtmlSelectionObject);
            BSTR bstr;
            pHtmlSelectionObject->get_type(&bstr);
            if (_tcscmp(_tcsupr(bstr),L"TEXT")!=0)
            {
                spHTMLDoc->get_body(&pHtmlElement);
                pHtmlElement->get_innerText(&bstr);
            }
            else
            {
                IHTMLTxtRange* pHtmlTxtRange;
                pHtmlSelectionObject->createRange((IDispatch**)&pHtmlTxtRange);
                pHtmlTxtRange->get_text(&bstr);
            }
            DWORD dwThreadID=0;
            CreateThread(NULL,0,speakThread,(LPVOID)bstr,0,&dwThreadID);
        }
    }

    return hr;
}

In the Exec function, which the browser calls when the menu item is selected, a couple of things are performed. First we ask the browser for a copy of the HTML. Next we create an IHTMLSelectionObject interface and check whether or not any text is selected. If there is text selected, then we create a range and get the text, if not, we get the body and get the text from the inner body of the HTML. Finally we create a thread and pass it the text we received from our selection or body of the HTML.

Notes

  • A thread must be created or else Internet Explorer will lock up until the text is finished reading.
  • If there is hidden text on the page, this will read all of the hidden text, such as links on MSDN's website.
  • This method allows you to view other pages without waiting for the text to finish reading, however no stopping mechanism is implemented in the API, so the user has to wait until the text is finished before a new selection can be made and read.

Things I Would Like To See

  • An Adobe Acrobat version
  • A Microsoft Word version
  • A method of skipping and replaying paragraphs added

History

  • 21st April, 2008: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Fred Ackers

Web Developer

United States United States

Member

Programming using MFC and ATL for almost 12 years now. Currently studying Operating System implementation as well as Image processing. Previously worked on DSP and the use of FFT for audio application. Programmed using ADO, ODBC, ATL, COM, MFC for shell interfacing, databasing tasks, Internet items, and customization programs.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralVery Good PinmemberLeslieM22:29 28 Apr '08  
GeneralRe: Very Good PinmemberFred Ackers16:31 29 Apr '08  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web04 | 2.5.120517.1 | Last Updated 21 Apr 2008
Article Copyright 2008 by Fred Ackers
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid