如何找出插入符号[在歌剧中]?

时间:2013-08-09 22:57:20

标签: c# winapi opera ui-automation

我正在尝试解决以下任务: 我有OPERA浏览器,我想知道,是否随时存在插入符号(文本光标)。例如,我点击地址栏,我想知道插入符号现在闪烁。然后我点击页面上的空白位置,我知道没有插入符号。

换句话说,我想定义一些文本元素现在是焦点。

我知道如何在许多应用程序中解决此任务,其中一些使用标准的Windows控件,如Edit,因此我可以获得焦点窗口并使用WinApi检查它的类。

在其他应用程序中,控件在没有本机窗口的情况下呈现,我可以使用Automation UI获取它。

但遗憾的是,Opera只有一个主窗口,并且不提供UI自动化技术的访问权。

那么,有人知道如何实现我的目标吗?)

编辑:

感谢Eric Brown,这是问题的解决方案:

// ConsoleForMSAA.cpp: определяет точку входа для консольного приложения.
//

#include "stdafx.h"
#include <OleAcc.h>
#include <iostream>

#pragma comment (lib, "oleacc.lib")

void ProcessCaretPos(HWND hwnd);

int _tmain(int argc, _TCHAR* argv[])
{

    for (;;)
    {
        // active toplevel window
        HWND hwnd = GetForegroundWindow();

        // current thread
        DWORD currentThreadId = GetCurrentThreadId();

        DWORD targetThreadId, targetProcessId;

        // target process and thread
        targetThreadId = GetWindowThreadProcessId(hwnd, &targetProcessId); 

        // attach current thread to target thread messaging queue
        BOOL attached = AttachThreadInput(currentThreadId, targetThreadId, true);

        // что это даст? Мы участвуем в обработке сообщений того потока
        // и все сис. вызовы, которые мы сделаем, будут посланы от имени того потока.
        if (attached)
        {
            try
            {
                // get focused window handle (focused child that of toplevel window)
                HWND targetWindow = GetFocus();

                // some procedure 
                ProcessCaretPos(targetWindow);
            }
            catch(...) {;}

            AttachThreadInput(currentThreadId, targetThreadId, false);
        }

        Sleep(1000);
    }
    return 0;
}

// 
void ProcessCaretPos(HWND hwnd)
{
    IAccessible *pAccCaret = NULL;

    VARIANT varCaret;
    RECT rcCaret;
    varCaret.vt = VT_I4;
    varCaret.lVal = CHILDID_SELF;

    if (SUCCEEDED(AccessibleObjectFromWindow(hwnd, OBJID_CARET, IID_IAccessible, (void **)&pAccCaret)))
    {
        HRESULT hr = pAccCaret->accLocation( &rcCaret.left, &rcCaret.top, &rcCaret.right, &rcCaret.bottom, varCaret);

        if (!hr)
        {
            std::cout << "caret positon: " << rcCaret.left << " " << rcCaret.top << " " << rcCaret.right << " " << rcCaret.bottom << "\n";
        }
        else
            std::cout << "there is nothing carets" << "\n"; 

        pAccCaret->Release();
    }
}

1 个答案:

答案 0 :(得分:1)

你可能运气不好。但是,如果Opera使用系统插入符号(例如,它可能不是; IE不会),您可以尝试使用MSAA查询系统插入符位置:

IAccessible *pAccCaret = NULL;

VARIANT varCaret;
RECT rcCaret;
varCaret.vt = VT_I4;
varCaret.lVal = CHILDID_SELF;

if (SUCCEEDED(AccessibleObjectFromWindow(hwnd, OBJID_CARET, IID_IAccessible, (void **)&pAccCaret)))
{
     hr = pAccCaret->accLocation( &rcCaret.left, &rcCaret.top, &rcCaret.right, &rcCaret.bottom, varCaret);

     pAccCaret->Release();
}