Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Глобальный хук на мышь WH_MOUSE_LL  (Прочитано 18141 раз)
0 Пользователей и 1 Гость смотрят эту тему.
v.korleone
Помогающий

ua
Offline Offline

« : 27-11-2009 05:13 » 

Здравствуйте. Пишу на MS VS 2008. Моя программа блокирует доступ пользователя на определенное время (время отдыха), после окончания  времени работы пользователя (по сути программа-таймер). Для блокирования клавиатуры использовал глобальный хук (WH_KEYBOARD_LL) в основу написания лег материал с http://www.sql.ru/forum/actualthread.aspx?tid=632552 + блокирование диспетчера задач, через изменение реестра.
Задача: с помощью хука (WH_MOUSE_LL) заблокировать доступ к мыше.
Вопрос:
 Не знаю как совместить хук клавиатуры и мыши.
Программа:
Код:
.....
        //Функция установки хука
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);

        //Функция снятия хука
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern bool UnhookWindowsHookEx(IntPtr hhk);

        //Функция передачи информации следующему приложению "слушающему" клавиатурные события
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr GetModuleHandle(string lpModuleName);
....
        private const int WH_KEYBOARD_LL = 13;
        private const int WM_KEYDOWN = 0x0100;
        private static LowLevelKeyboardProc _proc = HookCallback;
        private static IntPtr _hookID = IntPtr.Zero;
....
//*******************Функции для работы с Hook*****************************
        private void SetHook(LowLevelKeyboardProc proc)
        {
            if (_hookID != (IntPtr)0) return;  //исключаем повторный хук
            Process curProcess = Process.GetCurrentProcess();
            ProcessModule curModule = curProcess.MainModule;
            _hookID = SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0);
        }
       

        private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);

        // Функция которая обрабатывает события клавиатуры
        private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
        {
            return (IntPtr)1;
        }
....
private void timerRest_Tick(object sender, System.EventArgs e)
       {
            //присвоим делегат одной из переменных-членов класса, чтоб сборщик мусора не убрал
            // его после окончания первого же вызова функции
            _proc = new LowLevelKeyboardProc(HookCallback);
            // Включение режима
            KillCtrlAltDelete();//блокируем диспетчер задач
            SetHook(_proc); // устанавливаем хук         
                       countSec++;
           
// счетчик отдыха достиг порогового времени
if(countSec >= timeRest)
{
// оповещение пользователя
this.notifyIcon.Text = "Таймер не запущен!";

// отдохнули - можно приcтупать к работе
                // Выключение режима работы             
                LiveCtrlAltDelete();//Возобновляем работу диспетчера задач
                bool b = UnhookWindowsHookEx(_hookID);// снимаем хук
                if (b == false)
                {
                    throw new Exception("UnhookWindowsHookEx");
                }
                                                countSec = 0;
timerRest.Stop();
strPrompt = "Работа!";
pictureBox1.Invalidate();
panel1.Visible = false;
....
                             }


}
« Последнее редактирование: 27-11-2009 05:41 от v.korleone » Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #1 : 27-11-2009 05:19 » 

а зачем их совмещать - пусть у каждого своя процедура будет + общие переменные. Ну, по крайней мере, в с++ так возможно сделать
Записан

v.korleone
Помогающий

ua
Offline Offline

« Ответ #2 : 27-11-2009 05:45 » 

Типа такого?
Код:
...
 private const int WH_MOUSE_LL 14;
...
private void SetHooMouse(LowLevelKeyboardProc proc)
        {
            if (_hookID != (IntPtr)0) return;  //исключаем повторный хук
            Process curProcess = Process.GetCurrentProcess();
            ProcessModule curModule = curProcess.MainModule;
            _hookID = SetWindowsHookEx(WH_MOUSE_LL, proc, GetModuleHandle(curModule.ModuleName), 0);
        }
« Последнее редактирование: 27-11-2009 12:40 от v.korleone » Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #3 : 27-11-2009 05:56 » 

Цитата
Типа такого?
вопрос не понятен Улыбаюсь
зы кстати, если что - я в .NET не очень то
Записан

v.korleone
Помогающий

ua
Offline Offline

« Ответ #4 : 27-11-2009 12:41 » 

Разобрался. Начал делать хук для мыши по этому образцу:
Код:
class InterceptMouse
{
    private static LowLevelMouseProc _proc = HookCallback;
    private static IntPtr _hookID = IntPtr.Zero;

    public static void Main()
    {
        _hookID = SetHook(_proc);
        Application.Run();
        UnhookWindowsHookEx(_hookID);
    }

    private static IntPtr SetHook(LowLevelMouseProc proc)
    {
        using (Process curProcess = Process.GetCurrentProcess())
        using (ProcessModule curModule = curProcess.MainModule)
        {
            return SetWindowsHookEx(WH_MOUSE_LL, proc,
                GetModuleHandle(curModule.ModuleName), 0);
        }
    }

    private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam);

    private static IntPtr HookCallback(
        int nCode, IntPtr wParam, IntPtr lParam)
    {
        if (nCode >= 0 &&
            MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam)
        {
            MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
            Console.WriteLine(hookStruct.pt.x + ", " + hookStruct.pt.y);
        }
        return CallNextHookEx(_hookID, nCode, wParam, lParam);
    }

    private const int WH_MOUSE_LL = 14;

    private enum MouseMessages
    {
        WM_LBUTTONDOWN = 0x0201,
        WM_LBUTTONUP = 0x0202,
        WM_MOUSEMOVE = 0x0200,
        WM_MOUSEWHEEL = 0x020A,
        WM_RBUTTONDOWN = 0x0204,
        WM_RBUTTONUP = 0x0205
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct POINT
    {
        public int x;
        public int y;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct MSLLHOOKSTRUCT
    {
        public POINT pt;
        public uint mouseData;
        public uint flags;
        public uint time;
        public IntPtr dwExtraInfo;
    }

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr SetWindowsHookEx(int idHook,
        LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool UnhookWindowsHookEx(IntPtr hhk);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
        IntPtr wParam, IntPtr lParam);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr GetModuleHandle(string lpModuleName);
}
Что писать здесь, чтобы наглухо заблокировать мышь?
Код:
private static IntPtr HookCallback(
        int nCode, IntPtr wParam, IntPtr lParam)
    {
        if (nCode >= 0 &&
            MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam)
        {
            MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
            Console.WriteLine(hookStruct.pt.x + ", " + hookStruct.pt.y);
        }
        return CallNextHookEx(_hookID, nCode, wParam, lParam);
    }
« Последнее редактирование: 29-11-2009 07:54 от v.korleone » Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #5 : 29-11-2009 15:56 » 

попробуй
Код:
return 1;// CallNextHookEx(_hookID, nCode, wParam, lParam);
Записан

v.korleone
Помогающий

ua
Offline Offline

« Ответ #6 : 29-11-2009 18:55 » 

Алексей1153++, все работает - спасибо.
Остались последние штрихи программы. Нужно сделать следующие:
1. Программа-таймер должна включаться (т.е. производить отсчет времени работы пользователя) при любой активности пользователя (нажатие клавиши клавиатуры или движение/нажатие клавиши мыши);
2. Если более 3 минут нет активности пользователя (нажатие клавиши клавиатуры или движение/нажатие клавиши мыши), таймер должен останавливаться;
Прошу помощи с алгоритмом (это пока   Улыбаюсь ) данной программы.
P.S. Мне не понятен сам алгоритм работы моего будующего приложения, что за чем должно идти. Например, вот алгоритм:
1. Запуск приложения.
2. Запуск основного таймера (ОТ).
3. Установка хуков мыши+клавы (м+к).
4. После каждой активности м+к включать вспомогательный таймер (ВТ).
5. Если пользователь нажимает на клавишу клав-ры (аналогично для мыши) и время ВТ меньше 3 минут, прежнее время сбрасывается и начинается все по новому.
6. Если после последней нажатой клавиши, прошло 3 минуты приостановить ОТ, сбросить ВТ в 0.
7. Если ОТ приостановлен и нажата любая клавиша вновь запустить ОТ.
8. Все пункты начиная с 4 по 7 повторить.
Теперь вопрос, правильный ли ход мыслей? Если, что ни так поправьте. в общем пишите любые замечания.
« Последнее редактирование: 29-11-2009 20:56 от v.korleone » Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #7 : 30-11-2009 05:04 » 

таймер пусть тикает всегда, проверяясь при каждом тике на достижение 3 минут. А в хуках делаешь вот так

Код:

enum
{
e_timeout=3000 //мс
};

DWORD m_dwdTimeOut;//отсчитывает мс

...
{
...
if(m_dwdTimeOut>=e_timeout)
{
m_dwdTimeOut=e_timeout;
//своя логика в блокированном состоянии
//...

return 1;
}
else
{
m_dwdTimeOut=0;
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
}
« Последнее редактирование: 30-11-2009 05:07 от Алексей1153++ » Записан

v.korleone
Помогающий

ua
Offline Offline

« Ответ #8 : 09-12-2009 14:58 » 

Тема закрыта.
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines