2010-01-15 1 views
1

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

Итак, если у вас есть «я хочу ben |» где "|" представляет собой каретку, когда пользователь нажимает на клавиатуру, следующая буква определяется путем вычисления на предыдущих буквах слова «ben». Это может быть либо «d», либо «bend», либо «t»> «bent» и т. Д.

Это прекрасно работает, если я начинаю каждое слово с нуля, я могу просто отслеживать слово в строке в моей программе.

Проблема возникает, когда я устанавливаю каретку посредине слова. Мне нужно определить, какие персонажи приходят до позиции каретки. Ситуация также возникает, если я нажимаю клавиши со стрелками и т. Д.

В прошлом приложении AutoHotkey я сделал это, отправив команду «Shift + Ctrl + Left Arrow», чтобы выделить символы, команду «Ctrl + C», чтобы скопируйте его, а затем сохраните буфер обмена в моей строке. Я надеюсь, что на более надежном языке, таком как C#, я могу избежать уродливых осветительных артефактов этой техники. Есть ли способ получить символы программно?

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

Как вы думаете?

ответ

3

Там нет верный способ, чтобы получить «текущее текстовое поле». Любое приложение может развертывать свои собственные, поэтому вы не знаете, что искать. И если приложение не будет сотрудничать в таких вещах, вы не сможете его сильно заставить. Ну, я думаю, вы всегда можете попытаться захватить скриншот и попытаться сделать OCR на нем, но это не очень реалистично.

Однако приложение, написанное с использованием инструментария виджетов достойного качества (или с использованием элементов управления запасами), должно поддерживать Microsoft Active Accessibility, что обеспечивает стандартизованный способ доступа к пользовательскому интерфейсу этого приложения, а точнее, к абстрактному виду этого пользовательского интерфейса, который оптимизирован для извлечения из него информации такими инструментами, как считыватели экрана. Похоже на то, что вы хотите, за исключением того, что я не знаю способа получить информацию о тексте , предшествующий, выбор (каретка - это только выбор по ширине 0) из элемента управления с использованием MSAA.

+0

Спасибо, я посмотрю. – cksubs

0

Скорее всего, вам придется программно определить идентификаторы текстовых полей, которые редактируются, а затем отправить сообщение Windows (через PostMessage или SendMessage звонки), чтобы получить текст текстового поля. Я забыл, какое сообщение было необходимо для получения текста, но есть способ использования Windows API.

Перечисление C# сообщений, которые вы можете попробовать отправить в приложениях Windows, можно найти here.

Кроме того, я бы предложил отладку с помощью программы, такой как Spy ++ или Winspector spy.

+0

Это не будет работать вообще, потому что для этого приложения не нужно использовать элемент управления Win32 TEXTBOX. Например. Приложения Qt, Gtk и WPF используют собственные средства управления текстовыми полями.На самом деле, у них даже нет HWND ... –

3

Итак, с помощью обычного текстового поля .NET вы можете указать позицию каретки, используя свойство SelectionStart. Итак, что бы я сделал, это обнаружить, когда текст изменится и посмотреть, где находится карет. Вот некоторые быстрый пример кода вы можете адаптировать к вашей ситуации:

// first find the caret position 
int caretPosition = MyTextBox.SelectionStart; 

// now find all text that occurs before the caret 
string textUpToCaret = MyTextBox.Text.Substring(0, caretPosition); 

// now we can look for the last space character in the 
// textUpToCaret to find the word 
int lastSpaceIndex = textUpToCaret.LastIndexOf(" "); 

if (lastSpaceIndex < 0) 
    lastSpaceIndex = 0; 

string lettersBeforeCaret = textUpToCaret.Substring(lastSpaceIndex); 
+0

Это будет из текстового поля в форме моего собственного приложения, верно? Есть ли способ расширить это, чтобы сделать то же самое в текстовом поле любого приложения, что в настоящее время сосредоточено? Это сложнейшая проблема, с которой я сталкиваюсь. – cksubs

+0

К сожалению, нет. Проблема заключается в том, что вы не знаете, с какой технологией взаимодействует текстовое поле, с которым вы взаимодействуете, или если у вас даже есть крючки для вас, чтобы получить текст. Предположим, что это приложение GTK, например, имеет собственную реализацию TextBox. –