2016-10-26 2 views
2

Я пытаюсь реализовать средство выбора цвета, которое принимает цвет от пикселя во всем экране. Для этого я планирую использовать глобальный крючок мыши для прослушивания WM_MOUSEMOVE, чтобы обновить цвет при перемещении мыши и прослушивании щелчков мыши для подтверждения (WM_LBUTTONDOWN) или отмены (WM_RBUTTONDOWN) операции.Отключение мыши-крюка

Я следовал один из многих учебников вокруг, и я пришел с этим (в консольное приложение, просто чтобы проверить, если процесс работы):

static IntPtr hook; 
static bool click; 
static NativeMethods.LowLevelHookStruct llhs; 

static void Main(string[] args) 
{ 
    hook = NativeMethods.SetWindowsHookEx(NativeMethods.WH_MOUSE_LL, MouseHookCallback, (IntPtr)null, 0); 
    if (hook != IntPtr.Zero) 
    { 
    Console.WriteLine("Hook Set"); 
    while (!Console.KeyAvailable) { 
     Console.WriteLine("{0} {1} {2}", hook, llhs.pt.x, llhs.pt.y); 

     if(click) Console.WriteLine("click!"); 
     click = false; 

     System.Threading.Thread.Sleep(250); 
    } 
    } 
} 

и

public static IntPtr MouseHookCallback(int nCode, IntPtr wParam, IntPtr lParam) 
{ 
    if (nCode >= 0) 
    { 
    NativeMethods.LowLevelHookStruct hookStruct = (NativeMethods.LowLevelHookStruct)Marshal.PtrToStructure(lParam, typeof(NativeMethods.LowLevelHookStruct)); 

    if (NativeMethods.MouseMessages.WM_MOUSEMOVE == (NativeMethods.MouseMessages)wParam) 
    { 
     llhs = hookStruct; 
    } 

    if (NativeMethods.MouseMessages.WM_LBUTTONDOWN == (NativeMethods.MouseMessages)wParam) 
    { 
     click = true; 
    } 
    else if (NativeMethods.MouseMessages.WM_RBUTTONDOWN == (NativeMethods.MouseMessages)wParam) 
    { 
    } 
    } 

    return NativeMethods.CallNextHookEx(hook, nCode, wParam, lParam); 
} 

NativeMethods - это просто класс, в котором я храню все связанные с DllImport вещи.

После того, как я запускаю консольное приложение, курсор мыши застревает на пару секунд, и в консоли я получаю это - даже тогда, когда курсор является застрял

Hook Set 
3945554872 0 0 
3945554872 0 0 
3945554872 0 0 
3945554872 0 0 
... 

Отправляясь на него в отладке , кажется, что мой крючок никогда не называется, даже не один раз. Любая идея, что может быть неправильным?

+0

Я удалил тег из заголовка вашего вопроса. Пожалуйста, прочитайте [здесь] (http://stackoverflow.com/help/tagging) почему. – dymanoid

+0

Ах, забыл об этом. thanks :) – SirePi

+1

Крючок WH_MOUSE_LL требует цикла сообщений, чтобы Windows могла безопасно вызвать обратный вызов hook. Application.Run() в .NET-программе. Наиболее легко из проекта Winforms или WPF или одной из многих библиотек, которые делают это за вас. –

ответ

0

Следующее сообщение @Hans Passant Я переместил свой тестовый код в приложение WinForms, и появились обратные вызовы.

Тогда это был просто вопрос, чтобы выяснить, что обратный вызов был сборщиком мусора, так что все, что я должен был сделать, чтобы изменить

hook = NativeMethods.SetWindowsHookEx(NativeMethods.WH_MOUSE_LL, MouseHookCallback, (IntPtr)null, 0); 

в

private NativeMethods.LowLevelHookProc _hookCallback; 

... 

_hookCallback = new NativeMethods.LowLevelHookProc(MouseHookCallback); 
hook = NativeMethods.SetWindowsHookEx(NativeMethods.WH_MOUSE_LL, _hookCallback, (IntPtr)null, 0); 

для того, чтобы сохранить ссылку на обратный вызов, чтобы он не был GCed.