C# 如何确定[歌剧]中是否存在插入符号?

C# 如何确定[歌剧]中是否存在插入符号?,c#,winapi,opera,ui-automation,C#,Winapi,Opera,Ui Automation,我正在尝试解决以下任务: 我有OPERA浏览器,我想知道在任何时候是否存在插入符号(文本光标)。例如,我单击地址栏,我想知道插入符号现在正在闪烁。然后我点击页面上的空白处,我知道没有插入符号 换句话说,我想定义一些文本元素现在是焦点 我知道如何在许多应用程序中解决此任务,其中一些应用程序使用标准的windows控件(如Edit),因此我可以获得聚焦窗口并使用WinApi检查其类 在其他应用程序中,如果控件在没有本机窗口的情况下呈现,我可以通过自动化UI来实现这一点 但令我遗憾的是,Opera只有

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

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

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

在其他应用程序中,如果控件在没有本机窗口的情况下呈现,我可以通过自动化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();
    }
}
//ConsoleForMSAA.cpp:。
//
#包括“stdafx.h”
#包括
#包括
#pragma注释(lib,“oleacc.lib”)
无效处理CARETPOS(HWND HWND);
int _tmain(int argc,_TCHAR*argv[]
{
对于(;;)
{
//活动顶层窗口
HWND HWND=getforegroundindow();
//当前线程
DWORD currentThreadId=GetCurrentThreadId();
DWORD targetThreadId,targetProcessId;
//目标进程和线程
targetThreadId=GetWindowThreadProcessId(hwnd,&targetProcessId);
//将当前线程附加到目标线程消息传递队列
BOOL attached=AttachThreadInput(currentThreadId,targetThreadId,true);
// что это даст? Мы участвуем в обработке сообщений того потока
// и все сис. вызовы, которые мы сделаем, будут посланы от имени того потока.
如有(附件)
{
尝试
{
//获取聚焦窗口句柄(顶级窗口的聚焦子窗口句柄)
HWND targetWindow=GetFocus();
//一些程序
ProcessCaretPos(targetWindow);
}
捕获(…){;}
AttachThreadInput(currentThreadId、targetThreadId、false);
}
睡眠(1000);
}
返回0;
}
// 
无效处理CARETPOS(HWND HWND)
{
IAccessible*pAccCaret=NULL;
变异瓦卡雷;
矩形插入符号;
varCaret.vt=vt_I4;
varCaret.lVal=CHILDID\u SELF;
if(成功(从窗口访问对象(hwnd、OBJID_插入符、IID_IAccessible、(void**)和pAccCaret)))
{
HRESULT hr=pAccCaret->acclosition(&rcCaret.left,&rcCaret.top,&rcCaret.right,&rcCaret.bottom,varCaret);
如果(!hr)
{

std::cout您可能运气不好。但是,如果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();
}

Eric Brown,谢谢!我在opera中试用过,效果很好!此外,我在IE explorer中试用过这段代码,效果也很好!但是在IE和许多其他程序中,我必须先获得顶级窗口的聚焦元素,然后才能使用这段代码。将返回前台顶级窗口。对不起,没有问题)我使用了函数GetForeground()、GetWindowProcessThreadId()、AttachToThread()和GetFocus()。我认为函数GetGuitThreadInfo不适合我的用途,因为我想首先从mainWindow检索ThreadId,然后使用attach获取聚焦元素以创建ThreadId。如果通过AttachToThread()你的意思是
AttachThreadInput
,.
GetGuitThreadInfo
返回完全相同的数据,并且没有各种意外的要求。Eric,谢谢你的建议,但是视频质量很差,所以我不明白为什么使用AttachThreadInput是一种不好的方式。你能告诉我吗?另外,我试过GetGuitThreadInfo,但效果很差rks,但我不喜欢它需要用sizeof(这个结构)来填充CbSize字段,所以我必须写不安全的构造或写神奇的数字,比如48)