windows 如何在Windows中获取光标下的单词?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4665045/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 15:57:48  来源:igfitidea点击:

How to get the word under the cursor in Windows?

c#windowswinapihookocr

提问by blez

I want to create a application which gets the word under the cursor (not only for text fields), but I can't find how to do that. Using OCR is pretty hard. The only thing I've seen working is the Deskperience components. They support a 'native' way, but I they cost a lot. Now I'm trying to figure out what is this 'native' way (maybe somehow of hooking). Any help will be appreciated.

我想创建一个应用程序来获取光标下的单词(不仅用于文本字段),但我找不到如何做到这一点。使用 OCR 非常困难。我见过的唯一工作是 Deskperience 组件。他们支持“本地”方式,但我他们花了很多钱。现在我试图弄清楚这种“本地”方式是什么(也许是某种方式的挂钩)。任何帮助将不胜感激。

EDIT:I found a way, but it gets only the whole text of the control. Any idea how to get only the word under the cursor from the whole text?

编辑:我找到了一种方法,但它只获取控件的整个文本。知道如何从整个文本中只获取光标下的单词吗?

采纳答案by Simon Mourier

On recent versions of Windows, the recommended way to gather information from one application to another (if you don't own the targeted application of course) is to use the UI Automationtechnology. Wikipedia is pretty good for more information on this: Microsoft UI Automation

在最新版本的 Windows 上,从一个应用程序向另一个应用程序收集信息的推荐方法(当然,如果您没有目标应用程序)是使用UI 自动化技术。维基百科非常好提供有关此的更多信息:Microsoft UI Automation

Basically, UI automation will use all necessary means to gather what can be gathered

基本上,UI 自动化将使用所有必要的手段来收集可以收集的内容

Here is a small console application code that will spy the UI of other apps. Run it and move the mouse over to different applications. Each application has a different support for various "UI automation patterns". For example, there is the Value pattern and the Text pattern as demonstrated here.

这是一个小的控制台应用程序代码,它将监视其他应用程序的 UI。运行它并将鼠标移到不同的应用程序上。每个应用程序对各种“UI 自动化模式”都有不同的支持。例如,这里展示了 Value 模式和 Text 模式。

static void Main(string[] args)
{
    do
    {
        System.Drawing.Point mouse = System.Windows.Forms.Cursor.Position; // use Windows forms mouse code instead of WPF
        AutomationElement element = AutomationElement.FromPoint(new System.Windows.Point(mouse.X, mouse.Y));
        if (element == null)
        {
            // no element under mouse
            return;
        }

        Console.WriteLine("Element at position " + mouse + " is '" + element.Current.Name + "'");

        object pattern;
        // the "Value" pattern is supported by many application (including IE & FF)
        if (element.TryGetCurrentPattern(ValuePattern.Pattern, out pattern))
        {
            ValuePattern valuePattern = (ValuePattern)pattern;
            Console.WriteLine(" Value=" + valuePattern.Current.Value);
        }

        // the "Text" pattern is supported by some applications (including Notepad)and returns the current selection for example
        if (element.TryGetCurrentPattern(TextPattern.Pattern, out pattern))
        {
            TextPattern textPattern = (TextPattern)pattern;
            foreach(TextPatternRange range in textPattern.GetSelection())
            {
                Console.WriteLine(" SelectionRange=" + range.GetText(-1));
            }
        }
        Thread.Sleep(1000);
        Console.WriteLine(); Console.WriteLine();
    }
    while (true);
}

UI automation is actually supported by Internet Explorer and Firefox, but not by Chrome to my knowledge. See this link: When will Google Chrome be accessible?

Internet Explorer 和 Firefox 实际上支持 UI 自动化,但据我所知 Chrome 不支持。请参阅此链接:Google Chrome 何时可以访问?

Now, this is just the beginning of work for you :-), because:

现在,这只是您工作的开始:-),因为:

  • Most of the time, all this has heavy security implication. Using this technology (or direct Windows technology such as WindowFromPoint) will require sufficient rights to do so (such as being an administrator). And I don't think DExperience has any way to overcome these limitations, unless they install a kernel driver on the computer.

  • Some applications will not expose anything to anyone, even with proper rights. For example, if I'm writing a banking application, I don't want you to spy on what my application will display :-). Other applications such as Outlook with DRM will not expose anything for the same reasons.

  • Only the UI automation Text pattern support can give more information (like the word) than just the whole text. Alas, this specific pattern is not supported by IE nor FF even if they support UI automation globally.

  • 大多数时候,所有这些都具有严重的安全隐患。使用此技术(或直接的 Windows 技术,例如 WindowFromPoint)将需要足够的权限(例如作为管理员)。而且我不认为 DExperience 有任何方法可以克服这些限制,除非他们在计算机上安装内核驱动程序。

  • 某些应用程序不会向任何人公开任何内容,即使具有适当的权限。例如,如果我正在编写银行应用程序,我不希望您窥探我的应用程序将显示的内容:-)。出于同样的原因,其他应用程序(例如带有 DRM 的 Outlook)不会公开任何内容。

  • 只有 UI 自动化文本模式支持才能提供比整个文本更多的信息(如单词)。唉,即使它们全局支持 UI 自动化,IE 和 FF 也不支持这种特定模式。

So, if all this does not work for you, you will have to dive deeper and use OCR or Shape recognition techniques. Even with this, there will be some cases where you won't be able to do it at all (because of security rights).

因此,如果所有这些都不适合您,您将不得不深入研究并使用 OCR 或形状识别技术。即便如此,在某些情况下,您将根本无法做到这一点(因为担保权)。

回答by Simon Mourier

This is non-trivial if the application you want to "spy" on is drawing the text themselves. One possible solution is to trigger the other application to paint a portion of it's window by invalidating the area directly under the cursor.

如果您要“监视”的应用程序自己绘制文本,则这很重要。一种可能的解决方案是通过使光标正下方的区域无效来触发另一个应用程序来绘制其窗口的一部分。

When the other application paints, you will have to intercept the text drawing calls. One way to do so is to inject code in the other application, and intercept calls into GDI functions that draw text. When you debug native applications, this is what visual studio does to implement breakpoints. To test the idea you could use a library like detours(but that's not free for commercial use).

当其他应用程序绘制时,您将不得不拦截文本绘制调用。一种方法是在另一个应用程序中注入代码,并拦截对绘制文本的 GDI 函数的调用。当您调试本机应用程序时,这就是 Visual Studio 为实现断点所做的。为了测试这个想法,你可以使用像detours这样的库(但这不是免费的商业用途)。

You could also check if the application supports one of the accessability API's that are in Windows to facilitate things like screen readers for blind people.

您还可以检查应用程序是否支持 Windows 中的可访问性 API 之一,以便为盲人提供屏幕阅读器之类的功能。

One word of caution: I have not done any of this myself.

一个警告:我自己没有做过任何这些。

回答by baalazamon

If the app need to handle not only .Net apps I would start with importing functions (P/Invoke):

如果应用程序不仅需要处理 .Net 应用程序,我将从导入函数 ( P/Invoke) 开始:

Later you can iterate over the controls and try to get the text from inside based on type. If I will find some time I will try to publish such code.

稍后您可以遍历控件并尝试根据类型从内部获取文本。如果我能找到一些时间,我会尝试发布这样的代码。

After some checking it looks like the best way (unfortunately the hard also) is to hook into GDI text rendering some discussion

经过一些检查,看起来最好的方法(不幸的是也很难)是挂钩 GDI 文本呈现一些讨论

回答by Jonathan Wood

I'd echo what Patricker said, but I think there is no reliable way to do what you want.

我会回应帕特里克所说的,但我认为没有可靠的方法来做你想做的事。

You probably obtained the window text or something like that. But what if the cursor is over a window that doesn't use the window text to store its content? Windows are under no obligation to store their data in a particular way.

您可能获得了窗口文本或类似的内容。但是如果光标位于一个不使用窗口文本来存储其内容的窗口上呢?Windows 没有义务以特定方式存储其数据。

This ends up pointing you towards character recognition where you look at the pixels under the cursor and try and figure out what words are there. But not only is this very non-trivial, it also is not foolproof. What if part of the word is not visible because it extends out of the window?

这最终会引导您进行字符识别,您可以查看光标下的像素并尝试找出其中的单词。但这不仅非常重要,而且也并非万无一失。如果单词的一部分因为它伸出窗外而不可见怎么办?

This is definitely not trivial. There are a couple of ways to approach it. But there is no reliable way that will work with all windows.

这绝对不是小事。有几种方法可以解决它。但是没有可靠的方法适用于所有窗口。

回答by Giorgi

There is an sdk for getting the text using OCR. It's not free but it's quite cheap compared to other products: http://www.screenocr.com/screen-ocr-library-sdk.htmThey have an application which provides the same features so you can try the demo too.

有一个使用 OCR 获取文本的 SDK。它不是免费的,但与其他产品相比相当便宜:http: //www.screenocr.com/screen-ocr-library-sdk.htm他们有一个提供相同功能的应用程序,因此您也可以尝试演示。

回答by RichardB

To achieve this you need a multi-pronged approach.

为此,您需要多管齐下的方法。

UIA does work in many applications but you need to experiment to see where the text is returned. It may be in Element, Value or Range. There is no consistency even across office applications.

UIA 确实适用于许多应用程序,但您需要进行试验以查看文本的返回位置。它可能在元素、值或范围中。即使跨办公应用程序也没有一致性。

If UIA fails then enumerate the running object table (ROT) and retreive the COM pointers to various apps registered in the ROT. You can then cast these pointers to the underlying office types:
for example:

如果 UIA 失败,则枚举运行对象表 (ROT) 并检索指向在 ROT 中注册的各种应用程序的 COM 指针。然后,您可以将这些指针转换为底层办公类型:
例如:

enumerate ROT  - then
 wb = (Excel._Workbook)enumerator.Value;
string strText = wb.Application.ActiveCell.Text.ToString();

If the above two methods fail then make use of the free OCR system in MODI (Microsoft Office Document Imaging 12.0 Type Library)

如果以上两种方法都失败了,那就使用 MODI 中的免费 OCR 系统(Microsoft Office Document Imaging 12.0 Type Library)