Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Глобальные хуки

9.7K
01 января 2012 года
Vitamant
228 / / 07.02.2011
Подскажите - возможно ли отлавливать сообщения, адресуемые конкретному окну?
К примеру, я хочу отловить сообщения добавления и удаления элементов из ComboBox.
Отлов всех сообщений с последующей фильтрацией меня совершенно не радует. Количество вызовов будет просто безумным. Даже если ограничиться одним методом-фильтром, который будет переадресовывать исключительно нужные сообщения другим методам, мне кажется, что пропускать через него все системные сообщения (в данном случае WH_CALLWNDPROC) - идея не самая лучшая...

Впрочем, я всегда перестраховываюсь, когда дело доходит до обработки больших объемов данных. Возможно, мои опасения беспочвенны?

В общем, посоветуйте, гуру!

P.S. Писать собираюсь на C#, используя библиотеку написанную на C, так как C# не позволяет использовать глобальные хуки, исключая обработку событий клавиатуры и мыши.
278
01 января 2012 года
Alexander92
1.1K / / 04.08.2008
А чем обусловлен выбор именно хуков для этой задачи? Не кажется ли вам, что легче организовать сабклассинг конкретного окна?
14
01 января 2012 года
Phodopus
3.3K / / 19.06.2008
1. Возможно
2. Чтобы отловить именно добавление/удаление все равно придется их фильтровать - так что не вижу большой разницы. Или не до конца понял
9.7K
02 января 2012 года
Vitamant
228 / / 07.02.2011
Alexander92
Можно подробнее? Что вы имели ввиду под сабклассингом? Просто окошко то не мое - именно поэтому и возникла необходимость в хуках. Скажем, диалог "Открыть файл" блокнота. По этой же причине нужны глобальные хуки - сообщения своего окошка я могу обработать.

Phodopus
1. Как? :)
2. Ну, если есть стандартная виндовая функция, которая будет передавать сообщения адресуемые исключительно контролу с хэндлом 6462232 и вызывать для него метод, который уже отфильтрует сообщения - это одно. А если в этот метод будут валиться все сообщения системы - это совсем другое. Есть какой-нибудь примерчик этого?

Вопрос скользкий - если это хоть как-то повередит производительности или стабильности - то я откажусь от этой затеи.
Если есть безопасное решение, которое не повлечет вышеозначенных проблем - реализую и буду донельзя счастлив. :)
7
02 января 2012 года
@pixo $oft
3.4K / / 20.09.2006
Узнаёшь адрес процедуры окна и меняешь.Щястье во все поля:)
9.7K
03 января 2012 года
Vitamant
228 / / 07.02.2011
Цитата: @pixo $oft
Узнаёшь адрес процедуры окна и меняешь.Щястье во все поля:)


Можно с этого места поподробнее? :)

7
03 января 2012 года
@pixo $oft
3.4K / / 20.09.2006
SetWindowLong и GWL_WNDPROC в помощь
9.7K
03 января 2012 года
Vitamant
228 / / 07.02.2011
Спасибо огромное! Кажется, это то что нужно!
---
Эх, да это действительно то что нужно... вот только, если я реализую эту штуку, она мне не понадобится. :D
Дело в следующем - как и в случае с хуком, мне придется внедриться в чужой процесс. =\
А если внедрюсь, то ничто не мешает повесить обычный хук. :)
7
03 января 2012 года
@pixo $oft
3.4K / / 20.09.2006
А для SetWindowLong нужно внедрение?И что ты имеешь в виду под «повесить обычный хук»—локальный WH_CALLWNDPROC,что ли?
9.7K
03 января 2012 года
Vitamant
228 / / 07.02.2011
Если верить msdn, да:
Цитата:
GWL_WNDPROC
-4

Sets a new address for the window procedure.
You cannot change this attribute if the window does not belong to the same process as the calling thread.



Ага. Именно локальный WH_CALLWNDPROC.

Извини, если я говорю странно - в WinAPI не силен, только недавно начал ковыряться.

P.S. А что - есть рабочий примерчик, говорящий об обратном? :D

277
03 января 2012 года
arrjj
1.7K / / 26.01.2011
Цитата:

К примеру, я хочу отловить сообщения добавления и удаления элементов из ComboBox.


Не думаю что это делается через сообщения, максимум придет репаинт для комбобокса.

Цитата:

Скажем, диалог "Открыть файл" блокнота.


Тут только WM_MENUSELECT можно отловить через wndproc, а вот если нажать Ctrl+O....:)


Ну это так оффтопик...

9.7K
04 января 2012 года
Vitamant
228 / / 07.02.2011
Цитата: arrjj
Не думаю что это делается через сообщения, максимум придет репаинт для комбобокса.
Тут только WM_MENUSELECT можно отловить через wndproc, а вот если нажать Ctrl+O....:)
Ну это так оффтопик...


*подавился*
В каком смысле?! О_О Если у нас стандартный контрол ComboBox, то добавление и удаление из него элементов происходит стандартными виндовыми сообщениями SendMessage/PostMessage.
Не считая тех, что добавились в момент инициализации.
Ну, а то, что некоторые вещи могут быть вызваны разными путями - эт понятно. :)

277
04 января 2012 года
arrjj
1.7K / / 26.01.2011
А, ну да, ([COLOR="silver"]чет я не туда прочитал ^^[/COLOR]) если стандартный mfc-шный то да, скорее всего ему придет CBEM_INSERTITEM или CB_ADDSTRING, а вот насчет (например) qt-шного виджета я чтото сильно сомневаюсь.
9.7K
04 января 2012 года
Vitamant
228 / / 07.02.2011
Цитата: arrjj
А, ну да, ([COLOR="silver"]чет я не туда прочитал ^^[/COLOR]) если стандартный mfc-шный то да, скорее всего ему придет CBEM_INSERTITEM или CB_ADDSTRING, а вот насчет (например) qt-шного виджета я чтото сильно сомневаюсь.


В Qt формочки не рисовал, так что не знаю. Но, кажется, Qt, как и Java, используют стандартные компоненты ОС, под которую было скомпилировано приложение. Возможно, это касается только графических библиотек. А, может, и WinAPI под виндой юзают... хотя вряд ли. Впрочем, обертку я делаю именно над WinAPI и Qt мне без надобности. :)

278
04 января 2012 года
Alexander92
1.1K / / 04.08.2008
Код:
WNDPROC oldWindowProc;
LRESULT CALLBACK NewWindowProc(HWND, UINT, WPARAM LPARAM);

HWND hWnd = тут вы как-то получаете дескриптор окна;
oldWindowProc = (WNDPROC)SetWindowLong(hWnd, GWL_WNDPROC, (LONG)newWindowProc);

// ...

LRESULT CALLBACK newWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  switch (uMsg) {
     case то_что_вам_надо:
       do_some_stuff();
       break;
  }
  return CallWindowProc(oldWindowProc, hWnd, uMsg, wParam, lParam);
}


Вот как-то так.
9.7K
05 января 2012 года
Vitamant
228 / / 07.02.2011
За попытку спасибо, но...

У нас есть метод oldWindowProc, который обрабатывает сообщения чужого потока и находится в чужом адресном пространстве.
У нас есть метод newWindowProc, которй мы хотим подсунуть, но который находится в нашем адресном пространстве.
У нас есть указатель (LONG)newWindowProc, который указывает на newWindowProc в нашем адресном пространстве.
У нас есть (WNDPROC)SetWindowLong, которая вернет указатель на oldWindowProc в чужом адресном пространстве.

...вот... Итого: в лучшем случае это работать не будет. В худшем - результат непредсказуем. ^^
Чтобы это заработало, нужно выделить в чужом процессе место для LRESULT CALLBACK NewWindowProc(HWND, UINT, WPARAM LPARAM);,
записать ее в этом место, передать на него указатель.

Помимо того, что я слабо себе представляю - как это делается, я более чем уверен, что процесс написанный на С++ или там Дельфи отнесется без понимания, к коду на C#, который ему нагло пытаются втюхать за родной. :)
278
06 января 2012 года
Alexander92
1.1K / / 04.08.2008
1. А что из этого вы пытаетесь делать на C#?
2. Насколько знаю, сабклассинг окон чужих процессов / потоков спокойно реализуется с использованием DLL.
9.7K
06 января 2012 года
Vitamant
228 / / 07.02.2011
Цитата: Alexander92
1. А что из этого вы пытаетесь делать на C#?
2. Насколько знаю, сабклассинг окон чужих процессов / потоков спокойно реализуется с использованием DLL.


1) Мне нужно в программе на C# отловить WinAPI-сообщения, посылаемые чужому окну. Всё. :)
Что будет между этим и чужим окном - C++, Ассемблер, ворох DLL - не важно. Главное, чтобы работало, и выполнялись следующие условия: аппаратно-независимость, безопасность (положим, что кривизна моих рук стремится к 0), быстродействие, совместимость с Windows XP, 7, 8 для элементов использующих WinAPI.
2) Как? :)

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог