Глобальные хуки
К примеру, я хочу отловить сообщения добавления и удаления элементов из ComboBox.
Отлов всех сообщений с последующей фильтрацией меня совершенно не радует. Количество вызовов будет просто безумным. Даже если ограничиться одним методом-фильтром, который будет переадресовывать исключительно нужные сообщения другим методам, мне кажется, что пропускать через него все системные сообщения (в данном случае WH_CALLWNDPROC) - идея не самая лучшая...
Впрочем, я всегда перестраховываюсь, когда дело доходит до обработки больших объемов данных. Возможно, мои опасения беспочвенны?
В общем, посоветуйте, гуру!
P.S. Писать собираюсь на C#, используя библиотеку написанную на C, так как C# не позволяет использовать глобальные хуки, исключая обработку событий клавиатуры и мыши.
2. Чтобы отловить именно добавление/удаление все равно придется их фильтровать - так что не вижу большой разницы. Или не до конца понял
Можно подробнее? Что вы имели ввиду под сабклассингом? Просто окошко то не мое - именно поэтому и возникла необходимость в хуках. Скажем, диалог "Открыть файл" блокнота. По этой же причине нужны глобальные хуки - сообщения своего окошка я могу обработать.
Phodopus
1. Как? :)
2. Ну, если есть стандартная виндовая функция, которая будет передавать сообщения адресуемые исключительно контролу с хэндлом 6462232 и вызывать для него метод, который уже отфильтрует сообщения - это одно. А если в этот метод будут валиться все сообщения системы - это совсем другое. Есть какой-нибудь примерчик этого?
Вопрос скользкий - если это хоть как-то повередит производительности или стабильности - то я откажусь от этой затеи.
Если есть безопасное решение, которое не повлечет вышеозначенных проблем - реализую и буду донельзя счастлив. :)
Можно с этого места поподробнее? :)
---
Эх, да это действительно то что нужно... вот только, если я реализую эту штуку, она мне не понадобится. :D
Дело в следующем - как и в случае с хуком, мне придется внедриться в чужой процесс. =\
А если внедрюсь, то ничто не мешает повесить обычный хук. :)
-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
К примеру, я хочу отловить сообщения добавления и удаления элементов из ComboBox.
Не думаю что это делается через сообщения, максимум придет репаинт для комбобокса.
Скажем, диалог "Открыть файл" блокнота.
Тут только WM_MENUSELECT можно отловить через wndproc, а вот если нажать Ctrl+O....:)
Ну это так оффтопик...
Тут только WM_MENUSELECT можно отловить через wndproc, а вот если нажать Ctrl+O....:)
Ну это так оффтопик...
*подавился*
В каком смысле?! О_О Если у нас стандартный контрол ComboBox, то добавление и удаление из него элементов происходит стандартными виндовыми сообщениями SendMessage/PostMessage.
Не считая тех, что добавились в момент инициализации.
Ну, а то, что некоторые вещи могут быть вызваны разными путями - эт понятно. :)
В Qt формочки не рисовал, так что не знаю. Но, кажется, Qt, как и Java, используют стандартные компоненты ОС, под которую было скомпилировано приложение. Возможно, это касается только графических библиотек. А, может, и WinAPI под виндой юзают... хотя вряд ли. Впрочем, обертку я делаю именно над WinAPI и Qt мне без надобности. :)
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);
}
Вот как-то так.
У нас есть метод oldWindowProc, который обрабатывает сообщения чужого потока и находится в чужом адресном пространстве.
У нас есть метод newWindowProc, которй мы хотим подсунуть, но который находится в нашем адресном пространстве.
У нас есть указатель (LONG)newWindowProc, который указывает на newWindowProc в нашем адресном пространстве.
У нас есть (WNDPROC)SetWindowLong, которая вернет указатель на oldWindowProc в чужом адресном пространстве.
...вот... Итого: в лучшем случае это работать не будет. В худшем - результат непредсказуем. ^^
Чтобы это заработало, нужно выделить в чужом процессе место для LRESULT CALLBACK NewWindowProc(HWND, UINT, WPARAM LPARAM);,
записать ее в этом место, передать на него указатель.
Помимо того, что я слабо себе представляю - как это делается, я более чем уверен, что процесс написанный на С++ или там Дельфи отнесется без понимания, к коду на C#, который ему нагло пытаются втюхать за родной. :)
2. Насколько знаю, сабклассинг окон чужих процессов / потоков спокойно реализуется с использованием DLL.
2. Насколько знаю, сабклассинг окон чужих процессов / потоков спокойно реализуется с использованием DLL.
1) Мне нужно в программе на C# отловить WinAPI-сообщения, посылаемые чужому окну. Всё. :)
Что будет между этим и чужим окном - C++, Ассемблер, ворох DLL - не важно. Главное, чтобы работало, и выполнялись следующие условия: аппаратно-независимость, безопасность (положим, что кривизна моих рук стремится к 0), быстродействие, совместимость с Windows XP, 7, 8 для элементов использующих WinAPI.
2) Как? :)