Разберём технологию написания бота. Когда мне понадобился такой бот, я похожей
статьи не нашёл (может плохо искал - теперь уже неважно). Бота я написал, пусть
будет теперь и статья.
Что нам понадобится?
1) Spy++ (Входит в состав MS Visual Studio).
2) Любая среда программирования, которая позволяет обращаться к Windows API. Лично я считаю
что работать с API и не иметь нормальных указателей - это не правильно. Поэтому я буду
пользоваться С++ Builder.
Будем писать бота для программы "МегаФон Интернет", которая будет автоматически рассылать
СМС. Точнее сказать программу то я уже написал давно, целей своих не добился (СМС-спам
рассылка), т. к. реальная скорость рассылки не превышает 10-15 СМС в минуту. Но полученный
опыт, как говориться, не пропьёшь.
Немного теории. Все элементы интерфеса программ Windows: кнопки, поля для ввода, меню, ...
все они являются окнами. Окну можно передавать сообщения функциями SendMessage(),
PostMessage(). Например SendMessage(ht, WM_LBUTTONDOWN, 0, 0) - нажатие левой кнопки
мыши на окне ht. Что такое ht? А это и есть главный описатель/указатель/идентификатор
окна - хэндл. Таким образом написание бота это поиск хэндлов нужных элементов и отправка
этим элементам нужных сообщений. Ещё важно напомнить что все окна в Windows выстроены в
древовидную структуру. Корень дерева - рабочий стол (его хэндл можно получить функцией
GetDesktopWindow()). Имея хэндл окна можно обратиться к соседнему окну справа, слева, выше
или ниже в дереве. Можно при желании обойти всё дерево. Это нам не понадобиться, а вот
определить положение нужного элемента относительно главного окна программы и затем
добраться до его хэндла, имея хэндл главного окна - это как раз то, чем и придётся
заниматься.
Начнём. Создаём проект и пишем такой код:
Код:
HWND ht
ht = FindWindow(NULL, "МегаФон Интернет");
То есть ищем хэндл главного окна программы, по его имени.
Включаем Spy++.Находим там нашу программу.
Для отправки СМС нам нужно сначала нажать кнопку "Новое".
Ищем её смещение относительно главного окна. Для этого перебираем все окна поддерева нашей
программы. И задаём в Spy++ вести лог событий для окна. И будем выводить в этот лог
только сообщение нажатия левой кнопки мыши WM_LBUTTONDOWN. CTRL+M вкладка Messages.
На вкладке Window ставим галочку Child Window. Это значит, что в лог будет записываться
не только сообщения для выбранного окна, а для всего поддерева. Так мы быстрее доберёмся
до нужного элемента.
Выбираем первое поддерево программы. Настраиваем лог, как я написал. Запускаем Spy++.
Нажимаем кнопку - ничего не пишется значит не то поддерево. Берём следующее поддерево.
Оп, вот оно сообщение.
Дальше раскрываем поддерево и делаем всё тоже самое для его веток.
Так постепенно добираемся до самого нужного окна - кнопки "Новое". То есть мы нашли его
смещение относительно главного окна.
Чтобы программно симитиривать нажатие левой кнопки мыши на кнопке "Новое", добираемся
до её хэндла. Будет выглядеть примерно так:
Код:
ht = FindWindow(NULL, "МегаФон Интернет");
ht = GetWindow(ht, GW_CHILD);
ht = GetWindow(ht, GW_HWNDNEXT);
ht = GetWindow(ht, GW_CHILD);
ht = GetWindow(ht, GW_HWNDNEXT);
ht = GetWindow(ht, GW_CHILD);
ht = GetWindow(ht, GW_CHILD);
ht = GetWindow(ht, GW_HWNDNEXT);
ht = GetWindow(ht, GW_HWNDNEXT);
ht = GetWindow(ht, GW_HWNDNEXT);
ht = GetWindow(ht, GW_HWNDNEXT);
ht = GetWindow(ht, GW_HWNDNEXT);
ht = GetWindow(ht, GW_CHILD);
ht = GetWindow(ht, GW_CHILD);
GW_HWNDNEXT - получаем хэндл следующего окна на том же уровне дерева. GW_CHILD - получаем
хэндл первого окна, на следующем уровне дерева.
Отправляем сообщения:
Код:
SendMessage(ht, WM_LBUTTONDOWN, 0, 0);
SendMessage(ht, WM_LBUTTONUP, 0, 0);
Кнопку нужно не только нажать но и отпустить.
После этого у нас выскакивает новое окно, которое так и называется "Новое". Ищем его в
трее Spy++. На этом окне нам нужно будет вбивать номера телефонов, текст самого
сообщения и нажимать кнопку "Отправить". Как нажимать кнопку объяснять ещё раз не буду.
Не буду объяснять и как найти хэндлы нужных элементов - всё как в первом случае. А вот
как вписать текст в поле для ввода объясню:
Код:
SendMessage(ht, WM_SETTEXT, 0, LPARAM("Превед!"));
Вот почти и всё, но не совсем. Прежде чем отправлять следуещее СМС, нужно дождаться
окончания отправки текущего СМС. Это называется интерактивность. Я это решил просто.
Пока окно "Новое" открыто, СМС ещё отправляется, когда окно закроется - СМС отправлено:
Код:
for(;;)
if(FindWindow(NULL, "Новое") == NULL) break;
Вот и всё.
Конечно задачи ботов могут быть намного сложнее. Например если нужно не дожидаясь
завершения одного действия начинать второе - тогда нужны потоки. Определить завершение
действия тоже может быть сложной задачей. Например по завершению действия, какой нибудь
значёк может окраситься в другой цвет. Но если есть Spy++, зацепиться всегда есть за что.
Самое гавное забыл написать - есть программы для написания простого бота (типа
запись макроса в MS Word). Можете их нагуглить и скачать. Вот только проблему
интерактивности они не решают, потоки в них также не создашь.
Всем удачи!