简体   繁体   中英

Microsoft TSF - Using ITfThreadMgr::GetFocus like IUIAutomation::GetFocusedElement

When I try to attach to Microsoft Text Services Framework (TSF) outside the context of a text service, I can't retrieve the information I need to interact with the active application's text.

#include <SDKDDKVer.h>
#include <stdio.h>
#include <tchar.h>
#include <msctf.h>
#include <atlbase.h>
#include <iostream>

// Macro throws a descriptive WCHAR* exception if(FAILED(hr))
#define OK(hrExpr)  do{std::cout<<"IN: "<<#hrExpr<<std::endl; HRESULT returnCode = hrExpr; if( FAILED(returnCode) ){std::cout<<std::endl<<"ERROR! "<<#hrExpr<<" @"<<__FILE__<<":"<<__LINE__<<" returned "<<returnCode<<std::endl; throw L#hrExpr; }else{std::cout << "OK: " << #hrExpr << std::endl;}}while(0)

int _tmain(int argc, _TCHAR* argv[])
{
    ::CoInitialize(0);

    ITfThreadMgr* pThreadMgr = NULL;
    TfClientId clientId = NULL;
    ITfDocumentMgr* docMgr = NULL;
    ITfContext* pContext = NULL;

    try
    {
        std::cout << "Use the next 5 seconds to switch to a TSF-enabled application and make a text selection." << std::endl;
        Sleep(5000);

        OK( CoCreateInstance(  CLSID_TF_ThreadMgr, 
                        NULL, 
                        CLSCTX_INPROC_SERVER, 
                        IID_ITfThreadMgr, 
                        (void**)&pThreadMgr) );

        OK( pThreadMgr->Activate(&clientId) );

        OK( pThreadMgr->GetFocus(&docMgr) );

        if (docMgr == NULL)
        {
            throw L"NULL document manager";
        }

        OK( docMgr->GetTop(&pContext) );

        // TODO: use ITfContext to get selection or make document edits
    }
    catch(LPCSTR msg)
    {
        std::wcout << L"Exception: " << msg << std::endl;
    }
    catch(LPCWSTR msg)
    {
        std::wcout << L"Exception: " << msg << std::endl;
    }

    if (pContext)
        pContext->Release();    

    if (docMgr)
        docMgr->Release();

    ::CoUninitialize();
    return 0;
}

I am using WordPad on Windows 7 as my target test application, and I make sure to have focus on WordPad by the time the TSF methods execute.

The program gets as far as trying to get the currently focused ITfDocumentMgr ( ITfThreadMgr :: GetFocus ), but the returned document manager is NULL. According to the API documentation this means there is no currently focused ITfDocumentMgr, however:

If I take a completely different approach: register a custom text service and receive a ITfThreadMgr reference through ITfTextInputProcessor::Activate , I am able to retrieve the focused ITfDocumentMgr for WordPad via ITfThreadMgr::GetFocus. However for various reasons I would prefer not to install a custom inproc text service.

Is there any way to hook into the TSF API across process boundaries, as is possible with AutomationElement.FocusedElement , IUIAutomation::GetFocusedElement or AccessibleObjectFromWindow ?

Text Services Framework doesn't work cross-process. There's neither proxies nor stubs available. Sorry.

Incidentally, your code is trying to get the focused doc manager for your process. You create the ITfThreadMgr using CLSCTX_INPROC_SERVER , which starts the thread manager in your process, not in the target.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM