Как получить слово под курсором в Windows? - PullRequest
49 голосов
/ 12 января 2011

Я хочу создать приложение, которое получает слово под курсором (не только для текстовых полей), но я не могу найти, как это сделать. Использование OCR довольно сложно. Единственное, что я видел в работе - это компоненты Deskperience. Они поддерживают «родной» путь, но я стою дорого. Теперь я пытаюсь выяснить, что это за «родной» способ (возможно, каким-то образом зацепить). Любая помощь будет оценена.

EDIT: Я нашел способ, но он получает только весь текст элемента управления. Любая идея, как получить только слово под курсором из всего текста?

Ответы [ 6 ]

50 голосов
/ 19 января 2011

В последних версиях Windows рекомендуемый способ сбора информации из одного приложения в другое (если, конечно, у вас нет целевого приложения) - это использование технологии UI Automation .Википедия довольно хороша для получения дополнительной информации об этом: Microsoft UI Automation

В основном, автоматизация пользовательского интерфейса будет использовать все необходимые средства для сбора того, что можно собрать

Вот небольшойкод консольного приложения, который будет следить за интерфейсом других приложений.Запустите его и наведите курсор мыши на разные приложения.Каждое приложение имеет различную поддержку различных «шаблонов автоматизации пользовательского интерфейса».Например, здесь представлены шаблон Value и текстовый шаблон.

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);
}

Автоматизация пользовательского интерфейса фактически поддерживается Internet Explorer и Firefox, но не Chrome, насколько мне известно.См. Эту ссылку: Когда будет доступен Google Chrome?

Теперь это только начало работы для вас :-), потому что:

  • В большинстве случаев все это имеет серьезные последствия для безопасности.Использование этой технологии (или прямой технологии Windows, такой как WindowFromPoint) потребует достаточных прав для этого (например, администратор).И я не думаю, что DExperience каким-либо образом преодолеет эти ограничения, если только они не установят драйвер ядра на компьютер.

  • Некоторые приложения не будут открывать что-либо кому-либо, даже с соответствующими правами,Например, если я пишу банковское приложение, я не хочу, чтобы вы шпионили за тем, что будет отображать мое приложение :-).Другие приложения, такие как Outlook с DRM, не будут предоставлять что-либо по тем же причинам.

  • Только поддержка текстового шаблона автоматизации пользовательского интерфейса может дать больше информации (например, слова), чем только весь текст.Увы, этот конкретный шаблон не поддерживается ни IE, ни FF, даже если они поддерживают глобальную автоматизацию пользовательского интерфейса.

Так что, если все это не работает для вас, вам придется погрузиться глубже и глубже.использовать OCR или методы распознавания фигур.Даже при этом в некоторых случаях вы вообще не сможете это сделать (из-за прав безопасности).

9 голосов
/ 12 января 2011

Это нетривиально, если приложение, за которым вы хотите «шпионить», рисует сам текст.Одним из возможных решений является запуск другого приложения для рисования части его окна путем аннулирования области непосредственно под курсором.

Когда другое приложение будет рисовать, вам придется перехватывать вызовы рисования текста.Один из способов сделать это - ввести код в другое приложение и перехватить вызовы в функциях GDI, которые рисуют текст.Когда вы отлаживаете нативные приложения, это то, что Visual Studio делает для реализации точек останова.Чтобы проверить идею, вы можете использовать такую ​​библиотеку, как обход (но она не бесплатна для коммерческого использования).

Вы также можете проверить, поддерживает ли приложение один из API-интерфейсов специальных возможностей, которые есть в Windows, чтобы упростить такие вещи, как программы чтения с экрана для слепых.

Одно слово предостережения: я сам этого не делал.

7 голосов
/ 12 января 2011

Если приложению нужно обрабатывать не только приложения .Net, я бы начал с импорта функций ( P / Invoke ):

Позже вы можете перебирать элементы управления и пытаться получить текст изнутри на основе типа.Если я найду время, я попытаюсь опубликовать такой код.

После некоторой проверки, похоже, что лучший способ (к сожалению, трудный) - подключиться к визуализации текста GDI некоторое обсуждение

5 голосов
/ 28 января 2011

Я бы повторил то, что сказал Патриккер, но я думаю, что нет надежного способа сделать то, что вы хотите.

Возможно, вы получили текст окна или что-то в этом роде.Но что, если курсор находится над окном, которое не использует текст окна для хранения своего содержимого?Windows не обязана хранить свои данные определенным образом.

В конечном итоге вы указываете на распознавание символов, когда вы смотрите на пиксели под курсором и пытаетесь выяснить, какие слова там есть.Но это не только очень нетривиально, но и небезопасно.Что если часть слова не видна, потому что она выходит за пределы окна?

Это определенно не тривиально.Есть несколько способов приблизиться к этому.Но нет надежного способа, который будет работать со всеми окнами.

2 голосов
/ 21 января 2011

Существует SDK для получения текста с помощью OCR. Это не бесплатно, но довольно дешево по сравнению с другими продуктами: http://www.screenocr.com/screen-ocr-library-sdk.htm У них есть приложение, которое предоставляет те же функции, поэтому вы можете попробовать демо тоже.

0 голосов
/ 20 июля 2011

Для достижения этого вам нужен многоплановый подход.

UIA работает во многих приложениях, но вам нужно поэкспериментировать, чтобы увидеть, где возвращается текст.Это может быть элемент, значение или диапазон.Нет согласованности даже между офисными приложениями.

Если происходит сбой UIA, перечислите таблицу запущенных объектов (ROT) и получите указатели COM на различные приложения, зарегистрированные в ROT.Затем вы можете привести эти указатели к базовым типам офисов:
, например:

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

Если вышеперечисленные два метода не сработали, используйте бесплатную систему OCR в MODI (Microsoft Office Document Imaging 12.0 TypeLibrary)

...