Как моей программе узнать, нажимались ли кнопки и двигалась ли мыш?
Можно конечно поставить Hooks на wh_mouse и wh_keyboard (HHOOK SetWindowsHookEx) но это долго и опасно, если моя программа повиснет или не пропкстит эти сообщения через себя а задержит их то будет крах системы....Хотя если всё правильно сделать то думаю всё должно быть ОК.
Поставь таймер и сохрани старые координаты мышы, и флажок который помести в обработчик мыши и клавы, по истечению тайма проверяй координаты мыши и флажок если ни чего не изменилось то переходи к другому коду, далее повторяется все заново и т.д.
Или такое не подходит - надо чтобы мышь могла взаимодействовать со всем подряд?
в любом случае если не хочешь монополизировать мышь обрабатывай дополнительно сообщения WM_SETFOCUS, WM_KILLFOCUS, WM_MOUSELEAVE(WM_NCMOUSELEAVE), то есть ты будешь отслеживать мишь только тогда когда она на твоем окне (фиксируй эти сообщения флажками и включай в свою логику отслеживания мыши и клавы):)
В своей то программе я без проблем могу отловить все сообщения мыши и кнопок, а если форма не отображается (прога в трее только) то как я отловлю мышь и клавиши? Как мне зачепиться за очередь системных сообщений или за очередь активного окна и выловить от туда мышь и кнопки? И таймеров кучу поставить - это не сложно, а вот сообщения активного окна другого приложения... задача похожа чисто хакерсакая и что-то мне подсказывает на чистых API решается....
Почему это долго и опасно? Установка хуков в данном случае - нормальное решение. К хакерству, кстати, никакого отношения не имеет. Опять же, почему твоя программа должна обязательно зависнуть?
Я ж говорю - если нет необходимости мыши что то делать с другими приложениями, и нужно все сообщения обрабатывать только у себя, даже находясь в трее - SetCapture и ReleaseCapture.
Кажется так и работает ICQ - у неё есть настройка времени, через которое она вешает AW или NA, и просмотрев код я нашёл там SetWindowsHookEx и пр.. из той же оперы, вот только все примеры написаны на расчёт опытных пользователей.... досадно...
А кто сказал, что хуки забирают сообщения? Вовсе нет. Как раз наоборот: некоторые типы хуков вообще не позволяют ни отбросить, ни изменить сообщение. В любом случае, всегда есть возможность просмотреть сообщение и передать его дальше по цепи. Почитай MSDN и всё поймёшь (особенно секцию "Return Values" функции MouseProc).
для мыши можно с помощью функции GetCursorPos запомнить положение курсора, а потом в потоке с ним сравнивать, чтоб прога не подвисала надо еще sleep в потоке добавить и все нормал будет.
GetCursorPos - хватает координаты только моей формы.... а вот с хуками разобрался, вынес в внешнюю DLL и теперь всё что угодно.... только вот не понял - там всего 2 хука а DLLка почти 200к весом или другой вариант получается 50к - ну это черезчур... думаю теперь как обрезать эдок до 20к хотябы... и не совсем понял как передавать моему хуку значения переменных, потом он обрабатывает их возвращает в мою прогу - тут return values - чтото заморочки... ещё не понял... хотя с хуками конечно задача решилась - но вот в проект ещё 1 файл попал - это не лучшее решение, хотелось бы сделать всё в 1 файле программы...
А вот с передачей переменных дело оччень хитрое. Дело в том, что в случае работы с хуками библиотека один раз загружается в адресное пространство твоего процесса, а потом в адресное пространство КАЖДОГО из процессов. В результате в системе имеется одновременно несколько копий. Код библиотеки, видимо, расположен по одному и тому же физическому адресу, а вот все данные, от есть адреса переменных, - по разным. Если в одной из копий изменится значение глобальной переменной, это никак не отразится на копиях этой же переменной в других процессах. К адресному пространству твоей программы из библиотеки тоже прямого доступа нет. Лично я для обмена информацией в подобном случае использовал мэппинг (CreateFileMapping, OpenFileMapping) и события (CreateEvent, OpenEvent) - для того, чтобы указать, что значения "глобальных" переменных были изменены. Наверное, есть и другие варианты.
но всётаки хотелось бы всё в одном файле сделать, без всяких примочек и попутных файлов вроде DLL... я сделал ещё одну функцию - она забирает глобальную для DLL переменную - из хуков и передаёт её мне - тут всё решилось, правдо не супер-пупер решение но работает 100% и без CreateFileMapping, OpenFileMapping) и (CreateEvent, OpenEvent) , ведь моя DLL только для меня и вызывается 1 раз в одном месте каждые 5 сек для проверки хуков... Вот так...
Так один раз или каждые пять секунд? Что-то я не понимаю. И то, что она только для тебя, не значит, что не создаются её копии для каждого процесса. Если хук глобальный и действует не только на события твоего приложения, библиотека будет по любому копироваться в каждый из процессов системы.
Каждые 5 секунд конечно, и копии конечно создаются, поставил messagebox на закрытие dll в ней самой - так то 2 то 3 а то и 4 раза вылетает, видимо действительно 2-3-4 копии создаётся....,но вот некоторые приложения как-то влияют на хук мыши, хук срабатывает даже тогда, когда мыш не подвижна, пришлось сделать проверку на координаты - в хук передаётся lParam - который является указателем на структуру мыши, а уже из этой структуры вытаскиваю POINT pt - x,y, но почему-то координаты там какие-то бредовые - то все 0 то одна из координат 0, то нормально выдаёт, видимо неправильно lParam привязываюу к указателю на структуру описания мыши...но удалось обмануть и фильтр "левых" вызовов мыши срабатывает...в общем-то задача решилась..не так как хотелось бы -всё в одном exe а с помощью dll, ну пусть так....
Вот инициализация хука
static HINSTANCE hinstDLL = LoadLibrary("wasteh.dll");
static HANDLE hmodHookP;
static HANDLE hmodHookM;
static HOOKPROC HP_Kp=(HOOKPROC)GetProcAddress(hinstDLL,"KeyboardProc");
static HOOKPROC HP_Mm=(HOOKPROC)GetProcAddress(hinstDLL,"MouseProc");
typedef int (ControlProc)(void);
ControlProc* pFunction;
pFunction=(ControlProc*)::GetProcAddress(hinstDLL,"ControlProc");
int qqq=(*pFunction)();
hk_keyb=SetWindowsHookEx(WH_KEYBOARD,HP_Kp,(HINSTANCE)hinstDLL,0);
hk_mouse=SetWindowsHookEx(WH_MOUSE,HP_Mm,(HINSTANCE)hinstDLL,0);// (HINSTANCE)hinstDLL
а вот сама dll
#include <stdafx.h>
#include <math.h>
int KeySost=0;
int m_x,m_y;
#ifdef __cplusplus
typedef struct {
POINT pt;
HWND hwnd;
UINT wHitTestCode;
ULONG_PTR dwExtraInfo;
} MOUSEHOOKSTRUCT_p, *PMOUSEHOOKSTRUCT_p;
extern "C" {
#endif
//MOUSEHOOKSTRUCT_p mymousestr;
//*MOUSEHOOKSTRUCT_p mymousestr;
static int (__stdcall *mymousestr)(MOUSEHOOKSTRUCT_p *);
__declspec(dllexport) MouseProc(int nCode, WPARAM wParam, LPARAM lParam);
__declspec(dllexport) KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam);
__declspec(dllexport) int ControlProc(void);
#ifdef __cplusplus
}
#endif
__declspec(dllexport) MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
{ if (nCode < 0) // do not process the message
return CallNextHookEx(0, nCode,wParam, lParam);
//&mymousestr= &lParam;
*((void**)&mymousestr)=&lParam;
MOUSEHOOKSTRUCT_p mymousestr;
int as_x=mymousestr.pt.x;
int as_y=mymousestr.pt.y;
static int as_old_x=0;
static int as_old_y=0;
m_x=as_x;
m_y=as_y;
//char asdfg[128];
//sprintf(asdfg,"%d %d %d %d %d",KeySost,as_x,as_y,LOWORD(wParam), HIWORD(wParam));
// MessageBox(NULL,asdfg,"MouseProc",MB_OK);
if ((abs(as_x-as_old_x)>50)&&(abs(as_y-as_old_y)>50))
{ // MessageBox(NULL,"MouseProc","MouseProc",MB_OK);
as_old_x=as_x;
as_old_y=as_y;
KeySost=0;
}
return CallNextHookEx(0, nCode, wParam, lParam);
}
__declspec(dllexport) KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{ if (nCode < 0) // do not process the message
return CallNextHookEx(0, nCode,wParam, lParam);
// char asdfg[128];
// sprintf(asdfg,"%d %d",m_x,m_y);
// MessageBox(NULL,asdfg,"MouseProc",MB_OK);
// MessageBox(NULL,"KeyboardProc","KeyboardProc",MB_OK);
KeySost=0;
return CallNextHookEx(0, nCode, wParam, lParam);
}
__declspec(dllexport) int ControlProc(void)
{
// char asdfg[128];
// sprintf(asdfg,"%d",KeySost);
// MessageBox(NULL,asdfg,"KeyboardProc",MB_OK);
if (KeySost==85) KeySost=170; //AAh
if (KeySost==0) KeySost=85; //55h
return KeySost; //вот проблема - всегда возвращает 0 ???? почему
}
А так я проверяю состояние по таймеру ((*pFunction)()== возвращает 0??
case WM_TIMER:
{
if (wParam == 8) // check mouse move???
{
// MessageBox(NULL,"timer8","dfdgse_xxxxx",MB_OK); // для пров
int asd;
if ((*pFunction)()==85)
{
keycount=0;
asd=85;
}
else
{
keycount=keycount+1;
asd=170;
}
// char asdghd[64];
// sprintf(asdghd,"%d %d",keycount,asd);
// MessageBox(NULL,"timer8",asdghd,MB_OK); // для пров
if (keycount==30) SendMessage(hwndDlg,WM_COMMAND,IDC_LISTSTAT,85); //10 сек интервал, 6 инт=1мин
if (keycount==60)
{ // 5 мин = 30 интервалов.
SendMessage(hwndDlg,WM_COMMAND,IDC_LISTSTAT,170);
keycount=31;
}
}
Вот интересно, возьмётся кто-то разбираться в твоём коде или нет? Я не возьмусь, однозначно. :) Ты можешь по-человечески объяснить, зачем используешь таймер и хуки в одной программе? Это 2 разных подхода к решению задачи, зачем их смешивать? А про обмен данными между разными экземплярами библиотеки и приложением, чтобы данные не терялись и не обнулялись, я уже писал: используй мэппинг. Может, я чего-то недопонял, но лезть в дебри чужого кода...
Делаю хуки для того, чтобы "ловить" сообщения от мыши и кнопок - даже не ловлю можно сказать :-)), а просто получаю факт о том что состояние устройств сменилось, и в самой dll ставлю переменную статическую в состояние отличное от 0, это и есть признак того, что кнопки и мыш НЕ двигались. В основном коде программы по таймеру делаю опрос этой DLL с помощьюб функции, которая просто возвращает эту переменную мне. Если было "движение" то переменная 0, если нет то отличная от 0. Так вот, эта переменная то выдаёт нормально значение то нет, хотя все сообщения хуки перехватывают - ставил MessageBox на хук мыши и кнопок - они вылетают сразу если начитаем нажимать кнопки и трогать мышь, но значение переменной теряется в самой DLL или при возврате её (переменной) в главную прогу. Вот этот мемент мне не понятен. Вроде можно делать глобальные "ШАРЕД" переменные для всех копий этой DLL загруженных в памяти (может из-за этого данные переменной то есть а то и нет..) но как это сделать честно я не знаю... :-((((...