В C # есть ли способ последовательно получать выделенное текстовое содержимое текущего окна? - PullRequest
3 голосов
/ 17 марта 2009

В моем приложении c # .Net я пытался получить выбранный текст в текущем окне. (Обратите внимание, что это может быть любое окно, открытое в окнах, например, word или safari).

Я могу восстановить дескриптор текущего фокусированного элемента управления. (Используя пару вызовов взаимодействия для user32.dll и kernel32.dll).

Однако я не смог последовательно вернуть выбранный текст.

Я пытался использовать SENDMESSAGE и GET_TEXT. Однако, похоже, это работает только для некоторых приложений (работает для простых приложений, таких как WordPad, не работает для более сложных приложений, таких как Firefox или Word).

Я пытался использовать SENDMESSAGE и WM_COPY. Однако, опять же, похоже, что это работает только на некоторых элементах управления. (Я думаю, что WM_COPY вызовет то же поведение, что и нажатие CTRL-C вручную, но это не так).

Я пытался использовать SENDMESSAGE и WM_KEYUP + WM_KEYDOWN, чтобы вручную стимулировать команду копирования. Но это тоже не всегда работает. (Возможно, из-за совпадения с действующей горячей клавишей, нажимаемой пользователем для вызова моих приложений).

Есть какие-нибудь идеи о том, чтобы постоянно получать выбранный текст? (на любом приложении).

Ответы [ 7 ]

4 голосов
/ 16 марта 2012

Я получил это с помощью комбинации нескольких вещей. Итак:

  1. Подождите, пока все модификаторы удерживаются, чтобы быть выпущенными.
  2. Отправить элемент управления + c (используя этот ответ Триггер ОС для программного копирования (ctrl + c или Ctrl-x) )

            bool stillHeld = true;
            int timeSlept = 0;
    
            do
            {
                // wait until our hotkey is released
                if ((Keyboard.Modifiers & ModifierKeys.Control) > 0 ||
                    (Keyboard.Modifiers & ModifierKeys.Alt) > 0 ||
                    (Keyboard.Modifiers & ModifierKeys.Shift) > 0)
                {
                    timeSlept += 50;
                    System.Threading.Thread.Sleep(timeSlept);
                }
                else
                {
                    stillHeld = false;
                }
            } while (stillHeld && timeSlept < 1000);
    
            Keyboard.SimulateKeyStroke('c', ctrl: true);
    

Я использую WPF, поэтому Keyboard.Modifiers - это System.Windows.Input.Keyboard, а Keyboard.SimulateKeyStroke - из ответа Криса Шмика.

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

2 голосов
/ 19 января 2010

Мне удалось получить текст для WordPad / Блокнот и все, что поддерживает автоматизацию пользовательского интерфейса.

Код ниже может работать для вас в некоторых случаях. Я собираюсь начать использовать Reflector, чтобы увидеть, как Windows делает это для текстовых полей в свойстве TextBoxBase.SelectedText.

public static string SelectedText
{
    get
    {
        AutomationElement focusedElement = AutomationElement.FocusedElement;

        object currentPattern = null;

        if (focusedElement.TryGetCurrentPattern(TextPattern.Pattern, out currentPattern))
        {
            TextPattern textPattern = (TextPattern)currentPattern;
            TextPatternRange[] textPatternRanges = textPattern.GetSelection();
            if (textPatternRanges.Length > 0)
            {
                string textSelection = textPatternRanges[0].GetText(-1);
                return textSelection;
            }
        }
        return string.Empty;
    }
    set
    {
        AutomationElement focusedElement = AutomationElement.FocusedElement;
        IntPtr windowHandle = new IntPtr(focusedElement.Current.NativeWindowHandle);
        NativeMethods.SendMessage(windowHandle, NativeMethods.EM_REPLACESEL, true, value);
    }
}
1 голос
/ 17 марта 2009

Возможно, я неправильно понял вопрос, но не могли бы вы просто отправить Ctrl + c? Если вы знаете, что окно всегда впереди и выделен текст для копирования?

SendKeys.SendWait("^c");

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

1 голос
/ 17 марта 2009

Я не верю, что это возможно, в данный момент фокус может не содержать какой-либо выделенный текст. (Это может даже не содержать текст). Или текущим выбором может быть значок или изображение.

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

0 голосов
/ 31 июля 2009

Попробуйте API GetWindowText () для элементов управления, для которых другие методы не работают.

0 голосов
/ 18 марта 2009

Хм ... тебе это легко? Как получилось?

Лучшая альтернатива SendKeys.SendWait ("^ c"); Я нашел это:

http://www.c -sharpcorner.com / Форум / ShowMessages.aspx? ThreadID = 46203

Однако он работает только для нескольких приложений, таких как блокнот. Для веб-браузеров просто вылетает.

Кто-нибудь получил что-нибудь лучше?

0 голосов
/ 17 марта 2009

Я думаю, что создание монитора буфера обмена - хороший вариант. Я предлагаю вам взглянуть на Klipper (модуль буфера обмена KDE), он скопировал все, что вы выбрали в списке буфера обмена, содержимое - это файл, папка или какой-то текст.

Более подробную информацию можно найти здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...