Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.71/21: Рейтинг темы: голосов - 21, средняя оценка - 4.71
86 / 13 / 1
Регистрация: 24.05.2010
Сообщений: 590

Прочитать и изменить текст в стороннем приложении

31.08.2015, 15:00. Показов 4625. Ответов 33
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Привет!

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

До вставки текста обратно я пока не дошел, т.к. не получается хотя бы получить текст. Вот, что делаю для того, чтобы получить:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
    public partial class MainWindow : Window
    {
        #region APIs
 
        [DllImport("user32.dll")]
        public static extern bool GetCursorPos(out Point pt);
 
        [DllImport("user32.dll", EntryPoint = "WindowFromPoint", CharSet = CharSet.Auto, ExactSpelling = true)]
        public static extern IntPtr WindowFromPoint(Point pt);
 
        [DllImport("user32.dll", EntryPoint = "SendMessageW")]
        public static extern int SendMessageW([InAttribute] System.IntPtr hWnd, int Msg, int wParam, IntPtr lParam);
        public const int EM_GETSEL = 0x00B0;
 
        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        internal static extern IntPtr GetForegroundWindow();
 
        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        internal static extern IntPtr GetFocus();
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        internal static extern int GetWindowThreadProcessId(int handle, out int processId);
 
        [DllImport("user32", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
        internal static extern int AttachThreadInput(int idAttach, int idAttachTo, bool fAttach);
        [DllImport("kernel32.dll")]
        internal static extern int GetCurrentThreadId();
 
        [DllImport("user32", CharSet = CharSet.Auto, SetLastError = true)]
        internal static extern int GetWindowText(IntPtr hWnd, [Out, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpString, int nMaxCount);
 
        #endregion
 
        private DispatcherTimer timer = new DispatcherTimer();
 
        public MainWindow()
        {
            InitializeComponent();
 
            timer.Interval = TimeSpan.FromSeconds(2);
            timer.Tick += timer_Tick;
            timer.Start();
        }
 
        void timer_Tick(object sender, EventArgs e)
        {
            try
            {
                MultiLineTextBox.Text = GetTextFromFocusedControl();
            }
            catch (Exception exp)
            {
                MultiLineTextBox.Text += exp.Message;
            }
        }
 
        //Get the text of the focused control
        private string GetTextFromFocusedControl()
        {
            try
            {
                int activeWinPtr = GetForegroundWindow().ToInt32();
                int activeThreadId = 0, processId;
                activeThreadId = GetWindowThreadProcessId(activeWinPtr, out processId);
                int currentThreadId = GetCurrentThreadId();
                if (activeThreadId != currentThreadId)
                    AttachThreadInput(activeThreadId, currentThreadId, true);
                IntPtr activeCtrlId = GetFocus();
 
                return GetText(activeCtrlId);
            }
            catch (Exception exp)
            {
                return exp.Message;
            }
        }
 
        //Get the text of a control with its handle
        private string GetText(IntPtr handle)
        {
            int maxLength = 512;
            IntPtr buffer = Marshal.AllocHGlobal((maxLength + 1) * 2);
            SendMessageW(handle, EM_GETSEL, maxLength, buffer);
            string w = Marshal.PtrToStringUni(buffer);
            Marshal.FreeHGlobal(buffer);
            return w;
        }
    }
В результате ко мне приходят какие-то крякозяблы, причем независимо от того где находится курсор, выделен какой-либо текст или нет. Если в функции GetText в SendMessageW я передаю такие параметры:

C#
1
SendMessageW(handle, WM_GETTEXT, maxLength, buffer);
то я получаю весь текст активного поля ввода. Получается вроде нормально. Но хочу именно выделенный текст.
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
31.08.2015, 15:00
Ответы с готовыми решениями:

Можно ли программно изменить ресурсы в стороннем приложении
Я уже спрашивал про добавление ресурсов в программу которая запущена. Мне ответили что это невозможно. А как насчет другой программы?...

Отправить выбранный в стороннем приложении текст в буфер обмена
Как при выделении текста, в стороннем приложении, отправить его в буфер обмена.? Имитировать нажатие ctrl+c ? или есть другие варианты ...

Возможно ли изменить иконку (в стороннем приложении), которая находится в верхнем левом углу окна?
Господа возможно ли изменить иконку ( в стороннем приложении ) которая находиться в верхнем левом углу стороннего окна , если да , то...

33
86 / 13 / 1
Регистрация: 24.05.2010
Сообщений: 590
10.09.2015, 16:08  [ТС]
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Nalik Посмотреть сообщение
На чем сейчас зациклился? Напиши что нужно сделать?
Достать текст из word-а, проанализировать его и если это текст который нам нужен изменить его в worde?
Да, все верно. Проблема в том, что в Ворде, по всей видимости, внутри несколько окон и текст находится в каком-то из них. Я не знаю как мне добраться до нужного окна. Кроме того, я пробовал получить все дочерние окна Ворда, но у меня даже этого не вышло: получается 0 дочерних окон (как я это пробовал сделать - код в моем сообщении выше).
0
 Аватар для Nalik
176 / 124 / 49
Регистрация: 30.11.2012
Сообщений: 1,330
11.09.2015, 10:23
Я так понимаю обычными средствами до MS Word не добраться..

Мой неудачный эксперимент:
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
IntPtr Handle = FindWindow("OpusApp", null); //Главное окно
            IntPtr Handle1 = FindWindowEx(Handle, (IntPtr)null, "MsoCommandBarDock", null); //Дочернее окно
            IntPtr Handle2 = FindWindowEx(Handle, (IntPtr)null, "MsoCommandBarDock", null); //Дочернее окно
            IntPtr Handle3 = FindWindowEx(Handle, (IntPtr)null, "MsoCommandBarDock", null); //Дочернее окно
            IntPtr Handle4 = FindWindowEx(Handle, (IntPtr)null, "MsoCommandBarDock", null); //Дочернее окно
            IntPtr Handle5 = FindWindowEx(Handle, (IntPtr)null, "_WwF", null); //Дочернее окно
 
            IntPtr Handle6 = FindWindowEx(Handle5, (IntPtr)null, "_WwB", null); //Дочернее окно дочернего окна
            IntPtr Handle7 = FindWindowEx(Handle6, (IntPtr)null, "MsoCommandBar", null); //Дочернее окно дочернего окна дочернего окна
            IntPtr Handle8 = FindWindowEx(Handle6, (IntPtr)null, "MsoCommandBar", null); //Дочернее окно дочернего окна дочернего окна
            IntPtr Handle9 = FindWindowEx(Handle6, (IntPtr)null, "_WwG", null); //Дочернее окно дочернего окна дочернего окна
            char[] text = new char[32768]; //Объявляем массив
            SendMessage(Handle9, WM_GETTEXT, (IntPtr)32768, (char[])text); //Заносим в массив текст из окна
            textBox1.Text = new string(text); //Выводим текст в textbox
В textbox заносится текст "Документ Microsoft Word", а не содержимое документа..


Посмотри может это тебе поможет:
http://nullpro.info/2012/rabot... dokumenta/
https://msdn.microsoft.com/en-... .word.aspx
http://madlog.ru/index.php?topic=648.0

Добавлено через 5 минут
В последней ссылки вроде уже реализовано то что вам нужно. Поиск текста и его замена.
0
 Аватар для Nalik
176 / 124 / 49
Регистрация: 30.11.2012
Сообщений: 1,330
11.09.2015, 11:07
Куда проще с блокнотом.
Во вложении проект который получает текст из блокнота, анализирует его и если текст нужный изменяет его на другой.
P.s. Опечатка, вместо word создал проект world
Вложения
Тип файла: rar world.rar (52.6 Кб, 4 просмотров)
0
86 / 13 / 1
Регистрация: 24.05.2010
Сообщений: 590
15.09.2015, 17:37  [ТС]
Nalik, у меня та же петрушка. Из блокнота текст получается, а из Ворда "Документ Microsoft Word". Т.к. решения, как найти нужный элемент в Ворде - я не нашел, я решил пойти другим путем. Решил имитировать нажатие Ctrl + C и потом забирать данные из буфера. Вот пробую сделать контрол + ц:

C#
1
2
3
4
5
6
7
8
9
10
11
12
        private void SendCtrlC(IntPtr hWnd)
        {
            uint KEYEVENTF_KEYUP = 2;
            byte VK_CONTROL = 0x11;
            
            SetForegroundWindow(hWnd);
            keybd_event(VK_CONTROL, 0, 0, 0);
            keybd_event(0x43, 0, 0, 0);
            keybd_event(0x43, 0, KEYEVENTF_KEYUP, 0);
            keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
 
        }
Вот функция, которой получаю данные из буфера:

C#
1
2
3
4
5
6
7
8
9
10
11
        public string GetClipboardText()
        {
 
            string returnText = "";
            if (Clipboard.ContainsText(TextDataFormat.Text))
            {
                returnText = Clipboard.GetText(TextDataFormat.Text);
            }
 
            return returnText;
        }
И вот так пробую вызвать:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
            string selectedText = "";
 
            IntPtr hWnd = GetForegroundWindow();
 
            uint processId;
            uint activeThreadId = GetWindowThreadProcessId(hWnd, out processId);
 
            Process p = Process.GetProcessById((int)processId);
            appName = p.ProcessName;
 
            uint currentThreadId = GetCurrentThreadId();
            AttachThreadInput(activeThreadId, currentThreadId, true);
            focusedHandle = GetFocusWindow.GetFocusedHandle();
            SendCtrlC(focusedHandle);
            AttachThreadInput(activeThreadId, currentThreadId, false);
 
            selectedText = GetClipboardText();
Как проверяю: открываю блокнот, пишу там что-то, выделяю текст и по горячей клавише оно запускается. В результате текст, который был в блокноте в буфер не попадает. И что ещё я интересное заметил - в блокнот на выделенное место вставляется символ "с". Т.е. такое впечатление, что передается просто с, а не Ctrl + c.

Вместо SendCtrlC(focusedHandle) пробовал ещё SendCtrlC(hWnd), но тогда в буфер попадает в виде текста "hWnd".

Что ему и тут не хватает?
0
86 / 13 / 1
Регистрация: 24.05.2010
Сообщений: 590
21.09.2015, 09:24  [ТС]
Актуально.
0
169 / 132 / 29
Регистрация: 16.02.2013
Сообщений: 867
21.09.2015, 12:27
Можно конечно использовать тот способ - о котором я писал выше. Но может проще и правильней - в памяти текст искать? Как в памяти "Документ Microsoft Word" лежит - не смотрел, так что не пинать
0
86 / 13 / 1
Регистрация: 24.05.2010
Сообщений: 590
21.09.2015, 15:24  [ТС]
Winhttp22, если честно, с AutoIt не очень охота связываться по причине того, что хочется без чего-то "лишнего" это сделать.
Искать в памяти, мне кажется, тоже как-то чересчур сложно, тем более, что мне надо не весь текст, а именно выделенный.
Неужели как-то по проще нельзя с этим гадским Вордом это все сделать?
0
169 / 132 / 29
Регистрация: 16.02.2013
Сообщений: 867
21.09.2015, 17:30
V0fka, ну дело ваше, уговаривать не стану. Если охота "без чего лишнего"- тогда не используйте те же функции win api. Преимущество аутоита считаю в том - что можно дочерние окна искать с помощью Рег. выражений, если без него такое же делать - то это велосипед, и куча кода.
Не понял - какой выделенный текст нужно получить?
0
86 / 13 / 1
Регистрация: 24.05.2010
Сообщений: 590
21.09.2015, 17:42  [ТС]
Цитата Сообщение от Winhttp22 Посмотреть сообщение
Не понял - какой выделенный текст нужно получить?
Есть Вордовский файл. Выделяю в нем текст и хочу получить именно его, а не весь текст, который содержится в файле.
0
979 / 874 / 350
Регистрация: 26.04.2012
Сообщений: 2,647
21.09.2015, 20:21
Тут проблема не с нахождением нужного окна, а с тем, чтобы найти универсальный способ получить выделенный текст из нужного окошка... C обычными окнами, у которых есть дочерние типа Edit, понимающие все нужные сообщения, никаких проблем. Проблема с приложениями вроде гугл хрома и ворда-там вся страница выглядит для WinApi функций как одно окно без дочерних... и как оттуда что-то достать универсальным способом-я пока что не пойму... разве что с лютым извратом через буфер обмена... правда и времени долго заниматься этой темой нет совсем(
0
86 / 13 / 1
Регистрация: 24.05.2010
Сообщений: 590
22.09.2015, 09:31  [ТС]
EvilFromHell, я готов и не универсальным способом это сделать. У меня сейчас основная проблема - это именно в Ворде. Если подскажете способ как конкретно из Ворда это достать - мне этого, в рамках поставленной задачи, с головой хватит.
0
169 / 132 / 29
Регистрация: 16.02.2013
Сообщений: 867
23.09.2015, 21:52
V0fka, вам ведь не только текст вытащить надо - а еще и выделенный. Можно узнать - что за программа такая? Что делает?
0
86 / 13 / 1
Регистрация: 24.05.2010
Сообщений: 590
24.09.2015, 17:20  [ТС]
Winhttp22, печатаем что-то, потом смотрим, а там раскладка не та. Программа должна взять выделенный текст, "перевести" его на "нормальный" язык и запихнуть обратно на место выделенного текста. Все вроде получается (даже текст вставляется в Ворд, кажется; завтра проверю ещё), но вот не получается из Ворда вытянуть выделенный текст.
0
86 / 13 / 1
Регистрация: 24.05.2010
Сообщений: 590
09.11.2015, 18:48  [ТС]
Актуально. Решил свести задачу к Ctrl+C, читаем данные из буфера - потом вставляем обратно. Не могу Ctrl+C сделать. Пробую так:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[DllImport("user32.dll", SetLastError = true)]
static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);
 
public const int KEYEVENTF_EXTENDEDKEY = 0x0001; //Key down flag
public const int KEYEVENTF_KEYUP = 0x0002; //Key up flag
public const int VK_LCONTROL = 0xA2; //Left Control key code
public const int A = 0x41; //A Control key code
public const int C = 0x43; //A Control key code
 
public static void PressKeys()
{
            keybd_event((byte)VK_LCONTROL, 0, KEYEVENTF_EXTENDEDKEY, 0);
            keybd_event((byte)C, 0, KEYEVENTF_EXTENDEDKEY, 0);
            keybd_event((byte)C, 0, KEYEVENTF_KEYUP, 0);
            keybd_event((byte)VK_LCONTROL, 0, KEYEVENTF_KEYUP, 0);
}
Но нифига не получается, в буфер обмена ничего не попадает. Пробовал ещё разные варианты, которые находил в интернете. Все они крутились вокруг keybd_event. Но не один вариант успехом не увенчался.

Можно как-то это сделать?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
09.11.2015, 18:48

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

Как изменить текст Label в другом приложении?
Здравствуйте. Подскажите пожалуйста, как можно изменить Label на другом приложении. Знаю, что надо использовать дескриптор, но как это...

Авторизация в стороннем приложении
Всем привет , Я студент, решил углубиться в мир программирования и взял свой курс на освоение VBA and VBS.(как первый язык я думаю...

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

Заменить курсор в стороннем приложении
Есть стороннее win32 приложение, в котором есть свой кастомный курсор. Нужно посредством c++ скрыть этот курсор и отобразить в этом же...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
34
Ответ Создать тему
Новые блоги и статьи
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
Мобильное приложение ColorStep
pavlinmavlin 17.09.2026
Реализовал приложение Красный, Зеленый, Синий в Unity3d + c#. Название изменил на ColorStep. Приложение прошло модерацию и теперь доступно для скачивания. Делал его сам, шаг за шагом — и вот,. . .
Запрет дублирования строк в табличной части
Maks 13.09.2026
Реализация из решения ниже выполнена на нетиповом справочнике "Нормы ТО" с табличной часть "Виды ТО", разработанного в КА2, со следующими реквизитами: - ВидТО (СправочникСсылка. ВидыТО); - ВидГСМ. . .
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
Программа опроса у.з. расходомера SLS-720F
Argus19 02.09.2026
Программа опроса у. з. расходомера SLS-720F Программа опрашивает один раз в минуту три ультразвуковых расходомера SLS-720F через интерфейс RS-485 по протоколу Modbus RTU. Опрашиваются регистры. . .
Hyper-V: Компьютер должен поддерживать доверенный платформенный модуль 2.0.
Maks 31.08.2026
При установке Windows 11 на виртуальную машину Hyper-V 2-го поколения вылезла такая ошибка: Решение: в параметрах виртуальной машины, в разделе "Безопасность" (Security) активировать флаг. . .
Архитектура биовида Стива в Майнкрафте: Зачем бонобо кубический каннибализм
anaschu 30.08.2026
Кубический Вагинокапитализм в Minecraft: Математический инвариант ОДУ и рок Стивов-бонобо Главная задача разработанной «Модели Всего» — наглядно продемонстрировать наличие системной «судьбы». . .
Оттачиваю умение писать js программы.
russiannick 30.08.2026
Проектом выходного дня стало написание Книги шифров Виженера. Итогом стала версия 200, синий туман. Синий туман назван так, потому что замораживает текст под собой. Нажатие синих кнопок управляют. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru