Toujours dans le cadre du développement de mon Media Center EasyMedia Manager en WPF, j'ai entrepris l'interception des messages Windows lancés lorsque les boutons Play/Pause/Stop présents sur certains PC sont pressés :

Première chose que je me suis dis : hum facile, j'ai deux solutions, soit je surcharge la méthode WndProc, soit je crée une classe dérivant de IMessageFilter, que j'instancie dans ma fenêtre et que j'ajoute à l'application. Et bien non, pas du tout. En effet, la notion de Handle ayant disparu en WPF cette technique ne fonctionne plus. Mais, pas d'inquiétudes, une autre solution a été pensée par les développeurs du Framework pour faire de l'interopérabilité WPF / Win32 !

Le ComponentDispatcher (System.Windows.Interop)

La MSDN nous apprend que cette classe fournit au développeur les outils nécessaires au contrôle partagé entre Win32 et WPF de la pompe à message (file d'attente des messages) d'une application. Cette classe fournit des évènements intéressant, un tout particulièrement : ComponentDispatcher.ThreadPreprocessMessage. En effet, cet évènement est levé lorsque la pompe à messages de l'application reçoit un message du clavier (les boutons, même sur le pc, sont considérés comme évènements clavier). Intéressons nous au prototype d'une méthode appelée lorsque cet évènement est levé :

private void ComponentDispatcher_ThreadPreprocessMessage(ref MSG msg, ref bool handled)

{

}

Cette méthode prend en paramètre un objet de type MSG (en référence) ainsi qu'un booléen (par référence aussi) indiquant si le message est considéré comme attrapé ou non, afin de bloquer la progression de sa propagation. MSG est une structure représentant un message de la pompe à messages de l'application.

Pour attraper les messages associés aux touches de contrôles, nous allons tout simplement définir des constantes les représentant, et tester que notre message passé à la méthode ci-dessus soit l'un des messages que nous souhaitons intercepter :

public const int WM_COMMAND = 256;

public const int WM_PLAYPAUSE = 179;

public const int WM_STOP = 178;

public const int WM_NEXT = 176;

public const int WM_PREV = 177;

public const int WM_VOLUP = 175;

public const int WM_VOLDOWN = 174;

public const int WM_MUTE = 173;

WM_COMMAND est le message qui est envoyé lorsqu'un utilisateur sélectionne une commande depuis un Menu Item, ou lorsque qu'un raccourci clavier est lancé (i.e. nos boutons de contrôle, par exemple). Une fois que l'on connait ce message, il devient aisé de récupérer la valeur de chaque bouton, chose que j'ai fait, après quoi j'ai pu créer les constantes que vous voyez ci-dessus, et qui ne sont rien d'autre que la valeur de la propriété wParam du message msg.

Il ne vous reste plus qu'à faire un switch / case sur cette propriété afin de définir quelle action effectuer lors du clic sur Play, Pause ect…

if (msg.message == Win32.WM_COMMAND)

{

switch ((int)msg.wParam)

{

case Win32.WM_PLAYPAUSE:

Play();

break;

case Win32.WM_MUTE:

Mute();

break;

case Win32.WM_NEXT:

Next();

break;

case Win32.WM_PREV:

Previous();

break;

case Win32.WM_STOP:

Stop();

break;

case Win32.WM_VOLDOWN:

VolumeDown(0.1);

break;

case Win32.WM_VOLUP:

VolumeUp(0.1);

break;

}

}

Et magie, cela fonctionne. Ayant récupérée les valeurs de la propriété wParam moi-même (n'ayant trouvé aucune information précise et « officielle ») je ne garantie pas que cela fonctionne sur tous les PC. Néanmoins, j'ai eu l'occasion de le tester sur 3 portables différents sans soucis. Je pense tout de même que c'est un standard ! Le contraire serait plus qu'abérant !

A bientôt Wink !

Au total, 4 commentaire(s) posté(s) ! Poster un commentaire

comments Par arthenius, le mardi 5 août 2008 à 14:50 - quote

arthenius Sympa ca...plus simple d'utilisation en tout cas Smile

comments Par Julien Corioland, le mercredi 6 août 2008 à 08:57 - quote

Julien Corioland Oui, c'est sûr que l'utilisation est "plus simple". Cependant les IMessageFilter des Windows Form étaient bien plus pratique dans certains cas...

comments Par Bruno, le samedi 27 septembre 2008 à 11:30 - quote

Bruno Le systeme parait simple , mais une question :
Y a t il moyen de recuperer les touches pressées d'une telecomande par ce systeme ou un autres systeme doit etre utilisé ?

comments Par Julien Corioland, le samedi 27 septembre 2008 à 20:32 - quote

Julien Corioland [quote=Bruno]Y a t il moyen de recuperer les touches pressées d'une telecomande par ce systeme ou un autres systeme doit etre utilisé ? [/quote]

Pour être franc, je n'ai jamais essayé avec une télécommande. Mais partant du principe que j'intercepte ici les mêmes messages windows que ceux agissant sur le media player je pense. En effet, cela serait abérant de ne pas avoir conventionné ces messages.

A l'instinct je te dirai que le code ci-dessus fonctionne avec une télécommande.

Dans le cas contraire, ce système serait tout à fait utilisable, en interceptant les bons messages.

A tester ;)

comments Ajouter un commentaire

(Affichera votre icône Gravatar)  
[b][/b] - [i][/i] - [u][/u]- [quote][/quote]