Вверх ↑
Этот топик читают: Гость
Ответов: 321
Рейтинг: 10
#1: 2012-01-19 23:50:29 ЛС | профиль | цитата
Здравствуйте ув. пользователи форума ХиАсм. Подскажите пожалуйста следующее:
Возможно ли реализовать нажатие определенной клавиши в определенной программе без потери фокуса например над браузером, в котором я сейчас пишу это сообщение ?!
Можно конечно активировать (сделать активным окно), затем каким-либо образом переключаться обратно и так далее, но это не удобно =
Знаю, что в Дельфи такое реализовать можно...

Смысл схему вылаживать нет, но все же...
Add(MainForm,2953706,189,105)
{
Point(onKeyUp)
link(onKeyUp,15005478:doCompare,[(237,132)(237,111)])
}
Add(MouseEvent,14854824,308,42)
{
Point(Handle)
}
Add(If_else,15005478,252,105)
{
Op2=String(70)
link(onTrue,1543355:doText,[])
}
Add(Edit,1543355,308,105)
{
Left=5
Top=30
Width=120
Text="handle"
DataType=1
link(Str,14854824:Handle,[(314,89)(328,89)])
}
Add(KeyEvent,15137389,308,168)
{
Code=49
link(Handle,1543355:Text,[])
}
Add(Button,4076157,49,168)
{
Left=130
Top=30
Width=60
Caption="Start/Stop"
link(onClick,1899693:doSwitch,[])
}
Add(Switch,1899693,98,168)
{
Point(onOff)
Point(onOn)
link(onOff,2488597:doOff,[])
link(onOn,2488597:doOn,[])
}
Add(LED,2488597,161,168)
{
Left=195
Top=30
Width=20
Height=20
link(onChange,12160181:doCompare,[])
}
Add(Label,4056672,252,42)
{
Left=5
Top=10
Width=280
Height=17
Caption="Клавиша F (без потери фокуса над данным окном)......"
}
Add(Timer,759080,259,168)
{
Interval=500
Enable=1
link(onTimer,15137389:doPress,[])
}
Add(If_else,12160181,210,168)
{
Op2=String(1)
link(onTrue,759080:doTimer,[])
link(onFalse,759080:doStop,[])
}

карма: 1

0
vip
#1.1контекстная реклама от партнеров
Ответов: 3889
Рейтинг: 362
#2: 2012-01-19 23:53:36 ЛС | профиль | цитата
SendMessageKeyEvent
карма: 1

0
Ответов: 321
Рейтинг: 10
#3: 2012-01-20 00:01:22 ЛС | профиль | цитата
SendMessage интересный вариант, много ломал голову над ним и решил сдаться...
Перед тем как создать тему поискал на форуме, нашел 1 тему с похожей задачей и если не ошибаюсь там Вы (1nd1g0) что-то писали по этому поводу, но все же к общему выводу по работе компонента не пришли Короче не решили проблему того пользователя... МБ и не Вы, но...
Ладно, спрошу напрямую, не можете ли вы продемонстрировать как SendMessage работает ?! По принципу 1го поста... ?!
В той теме еще про сообщения спрашивалось, где команды брать некто разобраться не мог...
карма: 1

0
Гость
Ответов: 17029
Рейтинг: 0
#4: 2012-01-20 00:07:25 правка | ЛС | профиль | цитата


Редактировалось 10 раз(а), последний 2021-06-21 04:00:48
карма: 0

0
Ответов: 321
Рейтинг: 10
#5: 2012-01-20 00:19:35 ЛС | профиль | цитата
Потеря фокуса там про дочернюю форму много нашел, нашел еще возможно про свое, но там 113 чет сообщение какое-то...все трудно...
И у меня с кодировкой или чет проблемы там место кнопок иероглифы, если бы по русски, может бы и понял =\
карма: 1

0
Ответов: 273
Рейтинг: 29
#6: 2012-01-20 05:25:02 ЛС | профиль | цитата
Описывать процесс долго. Лучше покажу.
Качай этот архив тыц (4.3Мб)

Там пять файлов:
SendMessage.uvf - видео-тутор от меня.
uvPlayer.exe - плеер для uvf (можешь взять с оффсайта, если опасаешься вирусов).
Project1.sha - Заготовка жертвы. То окно, где будем нажимать кнопку.
Project2.sha - Заготовка охотника. Программа, которая посылает сообщения.
text.txt - тот текст, что видно в туторе. Ссылки и шаги.

Для начала запусти uvPlayer.exe и перетащи на него SendMessage.uvf
карма: 0

1
Голосовали:Master4eG
Ответов: 321
Рейтинг: 10
#7: 2012-01-20 14:32:01 ЛС | профиль | цитата
На всякий случай спрошу. Скажите пожалуйста кто знает, на всех ли ОС ClassName (имя класса окна) будет одинаковая ?!
То есть используя элемент FindWindow (Поиск Окна) с ClassName и Caption он 100% найдет нужное окно, если например это игра:
ClassName=GxWindowClassD3d
Caption=игра
tomas если ты обладаешь хорошими навыками использования ИмкСканера подскажи пожалуйста есть ли в *сообщении* нажать кнопку (с отпусканием) или нужно использовать WM_KEYDOWN+WM_KEYUP.

карма: 1

0
Ответов: 3889
Рейтинг: 362
#8: 2012-01-20 14:38:17 ЛС | профиль | цитата
Master4eG писал(а):
есть ли в *сообщении* нажать кнопку (с отпусканием) или нужно использовать WM_KEYDOWN+WM_KEYUP.

Неоднократно отвечали на этот вопрос на форуме, я - в том числе. На что Ваша программа реагирует, то и слать. Некоторые реагируют на одно, некоторые - на два сообщения, некоторые вообще плевать хотели на Ваши сообщения и читают клавиатуру напрямую...
карма: 1

0
Ответов: 321
Рейтинг: 10
#9: 2012-01-20 14:49:05 ЛС | профиль | цитата
Я имею ввиду одну программу в частности. Нашел сообщения WM_KEYDOWN,WM_KEYUP,WM_CHAR...
Интересно есть ли аналог WM_KEYDOWN+WM_KEYUP... Т.е как в HiAsm есть DoPress, что очень удобно...
карма: 1

0
Ответов: 3889
Рейтинг: 362
#10: 2012-01-20 15:00:16 ЛС | профиль | цитата
Master4eG писал(а):
Интересно есть ли аналог WM_KEYDOWN+WM_KEYUP... Т.е как в HiAsm есть DoPress, что очень удобно..

Так никто не мешает их слать, вот только совсем не факт, что их кто-то примет, проверьте на своей программе. Многие без фокуса ни на что не реагируют, и не факт, что они вообще именно на сообщения реагируют, даже с фокусом.
карма: 1

0
Ответов: 273
Рейтинг: 29
#11: 2012-01-20 16:20:09 ЛС | профиль | цитата
Вообще-то код накидал на коленке, а до этого как-то не приходилось пользоваться SendMessage.

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

Чтобы не было обломов, следует учесть две вещи:
*Некоторые сообщения возвращают ответ.
*Некоторые сообщения в параметрах lparam/wparam передают дополнительную информацию, без которой ничего не выйдет.
Для исключения таких ситуаций следует внимательно изучить все параметры выбранного сообщения, и желательно в первоисточнике.
Некоторые параметры необязательны, другие-же имеют сложную структуру(описанную в msdn), третьи вообще не используются. Так-же и с ответами.

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

ClassName=GxWindowClassD3d
Caption=игра
Для надежности имеет смысл применить компонент WinEnum. Он переберет окна по заголовкам и найдет нужное окно, а заодно скажет его класс (только он уже не нужен - хэндл уже есть).

Вообще игры, как и браузеры, не имеют WinApi, за исключением главного окна. Все внутри своего окна они рисуют самостоятельно. Потому если не удастся обмануть окно с помощью сообщений, останется только внедрить в игру свою процедуру. Это сложный путь, и я, например, его не потяну.
Например простейший сканер клавиатуры на blitz3D так и не удалось ничем обмануть - он железно вцепился в настоящую клавиатуру.
карма: 0

1
Голосовали:Konst
Ответов: 273
Рейтинг: 29
#12: 2012-01-22 11:57:00 ЛС | профиль | цитата
Народ требует продолжения.
Хорошо, попробую дать еще инфы. Хотя, повторяю, я в этом не спец - все добыто сейчас, и делаю это также впервые
Может подтянутся знатоки и подскажут что полезное - было бы неплохо.

Первое, что хотелось бы прояснить: Master4eG, тебе оно для чего? Колись. В потемках блуждать нет желания.

Давай покажу на примере Сапера.
Window Scanner, прицел на окно. Хэндл только один - главного окна.
Игровое окно отрисовывается самостоятельно, поэтому доступа к нему нет.

Итак, максимум, что возможно в окне, перекрытом другим - управление меню.
Как послать клик - не нашел. Точнее можно отдать команду на захват мыши, и провести щелчок. Но это уже не SendMessage - придется использовать WinApi, а таких готовых компонентов вроде нету. Если нужно - пиши в IC.

Что тебе нужно из источников информации:
*Азбука программирования в Win32 API (3-е изд.). П.В.Румянцев.
  и/или Win32 API. Эффективная разработка приложений. Юрий Щупак.
    Здесь мы будем искать подходящее сообщение (а также в google и window scanner'е)
*Справочник сообщений - win32.hlp
    Здесь мы будем смотреть параметры сообщения (в случае чего - поможет translate.google.ru)
*Коды сообщений
    Здесь мы будем смотреть коды сообщений, для отправки их в компонент SendMessage.

Допустим нам нужно выбрать уровень сложности "Любитель".
1.1 Ищем сообщения для взаимодействия с меню (см. Источники).
  Нашли: wm_command
1.2 Смотрим параметры сообщения (см. Справочник).
  Нашли:
    wID = LOWORD(wParam);
    wID = Specifies the identifier of the menu item
    wParam = wId
    hwndCtl = (HWND) lParam;
    hwndCtl = Otherwise, this parameter is NULL.
    hwndCtl = 0
    Return Values = If an application processes this message, it should return zero.
  Это означает следующее:
    В wparam нужно передать ID подпункта меню.
    lparam=0.
    При удачном приеме сообщения в ответ придет 0 (нам он не особо и нужен)
1.3 Выбираем в Window Scanner окно игры и нажимаем кнопку "Меню"
1.4 Щелкаем по пункту "Любитель" и смотрим ID: 522 (#20A)
1.5 Выбираем сообщение wm_command и в wparam вписываем #20A
1.6 Отсылаем сообщение (кнопка "письмо") и наблюдаем:
  Ага, оно - размер поля изменился.
1.7 Смотрим код сообщения (см. Источники) и переводим его в десятичный вид (Win калькулятором):
  wm_command=$111=273
1.8 Записываем:
  273(522,0)
  Где:
  273 - десятичный код wm_command
  522 - wparam, десятичный ID (Компонент SendMessage принимает только десятичные числа)
  0 - lparam

Создаем проект:
код
Add(MainForm,2953706,420,280)
{
Width=270
Height=52
Caption="MineRuller"
BorderStyle=1
Position=1
link(onCreate,10331873:doFind,[])
}
Add(WinEnum,10331873,483,287)
{
link(onFindWindow,14717890:doStrCat,[])
link(Caption,4040631:Value,[])
}
Add(Memory,4040631,483,238)
{
Default=String(Сапер)
}
Add(Button,910300,371,385)
{
Left=135
Width=65
Caption="Любитель"
link(onClick,5497166:doData,[])
}
Add(Edit,1552837,567,287)
{
Width=135
}
Add(SendMessage,12073427,483,385)
{
Point(Message)
link(Handle,10331873:Handle,[])
link(Message,3792509:Value,[])
}
Add(Memory,3792509,504,329)
{
Default=Integer(273)
}
Add(StrCat,14717890,525,287)
{
Str1="Найдено окно: "
link(onStrCat,1552837:doText,[])
}
Add(Button,5006305,371,427)
{
Left=200
Width=65
Caption="Новичок"
link(onClick,13943954:doData,[])
}
Add(DoData,5497166,420,385)
{
Data=Integer(522)
link(onEventData,16612951:doWork2,[])
}
Add(DoData,13943954,420,427)
{
Data=Integer(521)
link(onEventData,16612951:doWork3,[(466,433)])
}
Add(HubEx,16612951,462,385)
{
link(onEvent,12073427:doSendMessage,[])
}
Add(StyleXP,8336760,420,329)
{
}
В Memory над SendMessage храним код сообщения.
Параметр wparam передаем в потоке от кнопок.
Хэндл окна ищем по заголовку.
Запускаем игру, запускаем проект - он находит окно игры и пишет об этом.
Нажимаем кнопки - меняется поле игры (как через меню).

Принцип тот же, что и у прошлого урока. Главное найти нужное сообщение.
карма: 0

2
Голосовали:Konst, Master4eG
Ответов: 321
Рейтинг: 10
#13: 2012-01-23 04:32:49 ЛС | профиль | цитата
tomas еще раз огромное спасибо....
И в копилочку можно добавить бесценную программу Microsoft Spy++, которая поможет отследить передаваемые сообщение для каждого окна индивидуально...
карма: 1

0
Ответов: 313
Рейтинг: -9
#14: 2012-01-25 13:19:05 ЛС | профиль | цитата
Я хотелбы узнать, так как можно вручную узнать тот или иной код сообщения? Или это невозможно?
карма: 0

0
Ответов: 5446
Рейтинг: 323
#15: 2012-01-25 13:46:24 ЛС | профиль | цитата
mrvitya, если ты про расшифровку констант типа WM_PAINT или SB_LINEUP, то они описаны в файле WinUser.h, входящем в Microsoft Windows SDK. У меня он лежит в
c:Program Files (x86)Microsoft SDKsWindowsv7.0AIncludeWinUser.h 
карма: 1

0
Сообщение
...
Прикрепленные файлы
(файлы не залиты)