2010-07-11 4 views
2

J'ai réussi à faire fonctionner mon code de souris de bas niveau, mais il y a des comportements que j'observe que je ne comprends pas très bien. Tout fonctionne bien si je génère un thread qui installe le crochet de la souris. Quand je n'en ai plus besoin, je laisse le fil se détruire automatiquement à la sortie du programme, et j'imagine que je peux facilement terminer le fil explicitement. Cependant cela me rend mal à l'aise parce que je ne vais pas finir par appeler UnhookWindowsHookEx pour libérer les ressources de la souris. J'ai donc essayé d'inverser la logique dans mon programme de test. J'essaie de générer un thread qui dort un peu, puis écrit dans une variable globale. Ensuite, j'appelle la routine d'installation du hook depuis le thread primaire. Voici une boucle qui vérifie la variable globale et quitte la boucle le cas échéant. Ensuite, il sera capable de nettoyer après lui-même. Voici le code correspondant:Win32 - comment gérer le fil de mon crochet de souris

static int willQuit = 0; 
unsigned WINAPI MouseProcessingProc (void *param) { 
try { // will catch exceptions and not propagate them 
    HHOOK mousehook = SetWindowsHookEx(WH_MOUSE_LL, MouseHookProc, 
    NULL, 0); 
    if (mousehook == NULL) printf("Mousehook error %u\n",GetLastError()); 

    while(true) { 
    MSG msg; 
    if (GetMessage(&msg,0,0,0)) { 
    TranslateMessage(&msg); 
    DispatchMessage(&msg); 
    } 
    if (willQuit) { printf("willQuit no longer 0!\n"); break; } 
    printf("Looped\n"); 
    } 
    willQuit = 0; 
    UnhookWindowsHookEx(mousehook); 

    printf("Procedure completed without exceptional events.\n"); 
} catch (const std::string& s) { 
    printf("String exception: %s\n", s.c_str()); 
} catch (int i) { 
    printf("Int exception: %d\n", i); 
} catch (...) { 
    printf("Unknown default exception!\n"); 
} 
printf("Exiting thread execution.\n"); 
return 0; 
} 

void spawn() { 
printf("Spawning Mouse thread\n"); 
_beginthreadex(NULL,0,MouseProcessingThreadProc,NULL,0,0); 
} 

void run() { 
printf("Running Mouse routine\n"); 
MouseProcessingThreadProc(0); 
} 

void stop() { 
printf("Stopping Mouse routine\n"); 
willQuit = 1; 
} 

unsigned WINAPI threadproc(void *param) { 
    Sleep(500); 
    printf("Spawned thread says 3"); 
    Sleep(500); 
    printf("2"); 
    Sleep(500); 
    printf("1\n"); 
    Sleep(500); 
    printf("Spawned thread calls stop now -->\n"); 
    stop(); 
} 

int main() { 
    _beginthreadex(NULL,0,threadproc,NULL,0,0); // waiter and stopper thread 
    run(); // become the mousehook thread 
    printf("Completed\n"); 
    return 0; 
} 

Maintenant, ce qui se passe est que la petite boucle d'interrogation de message que j'ai (la boucle while) ne revient jamais vraiment de l'appel GetMessage, donc il ne peut jamais atteindre le point où il vérifie willQuit. J'ai vérifié ceci avec ces printf et gdb. Pourquoi GetMessage ne retourne pas? Y at-il une meilleure façon de configurer mon fil de crochet de souris? Ou est-ce que j'essaie de faire quelque chose que je ne suis pas supposé faire?

merci pour la lecture.

Répondre

1

Dans votre routine stop(), après avoir défini la variable willQuit, vous devrez également POSTER n'importe quel message sur le thread exécutant MouseProcessingProc, afin que GetMessage revienne. Voir PostThreadMessage API.

EDIT: Vous pouvez également utiliser un événement ou un autre objet de synchronisation au lieu d'utiliser les messages Windows et la pompe de message. Ainsi, la pompe de message serait remplacée par quelque chose comme WaitForSingleObject, un objet du noyau que vous pouvez signaler, comme un événement.

+0

Cela a beaucoup de sens. Maintenant, il semble plus approprié de simplement créer mon propre message de thread personnalisé, et lorsque les threads de gestion de la souris reçoivent le message de quitter, ils peuvent quitter eux-mêmes. Une solution très naturelle au problème! –

Questions connexes