86 / 13 / 1
Регистрация: 24.05.2010
Сообщений: 590

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

31.08.2015, 15:00. Показов 4636. Ответов 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
Ответ Создать тему
Опции темы

Новые блоги и статьи
Новая последнея моя музыка в SUNO
zorxor 05.10.2026
Здравствуйте, дорогие мои друзья! С большой радостью я хотел бы представить вам свою новую последнею музыку, которую сгенерировала мне по моей просьбе нейросеть SUNO. С уважением, zorxor. Это. . .
Nekobox - outbounds[0].transport: unknown transport type: raw
damix 01.10.2026
Фикс ошибки Правым кликом по серверу -> отладочная информация -> edit Заменить "net": "raw", на "net": "tcp", Нажать кнопку reload.
Программный домашний кинотеатр
russiannick 27.09.2026
Сподобился на программный домашний кинотеатр. В качестве ЯВУ по традиции выбрал js. В помощники взял Яндекс-Алису. Было создано три зала на разные интересы. исторические и ретро сериал Хичкок. . .
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
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. Опрашиваются регистры. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru