Question 114

Comment fermer un programme externe à mon application ?

Pour fermer un programme il suffit tout simplement d'envoyer le message WM_CLOSE à sa fenêtre principale. Et donc la première étape sera de rechercher cette fenêtre principale. Pour ce faire, il faut employer l'API FindWindow à laquelle on transmettra le titre de la fenêtre. Ensuite il ne reste plus qu'à envoyer le message WM_CLOSE. Voici maintenant le code :

Option Explicit

Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long

Private Const WM_CLOSE = &H10

Private Sub Form_Load()

    Dim hWnd As Long

    hWnd = FindWindow(vbNullString, "Lecteur CD")
    If hWnd <> 0 Then
        Call PostMessage(hWnd, WM_CLOSE, 0, 0)
    Else
        MsgBox "Impossible de trouver la fenêtre !", vbExclamation
    End If

End Sub

Comme vous pouvez le constater, nous avons employer l'API PostMessage pour envoyer notre message. Or vous trouverez sur Internet de nombreux exemples utilisant SendMessage. Quelle est la différence ? En fait il existe un paquet d'API permettant d'envoyer des messages, chacune ayant ses spécificités :

  • SendMessage : Cette fonction est synchrone. En d'autres mots, elle ne se terminera que lorsque le message aura été envoyé et traité. Cela peut poser des problèmes si vous envoyer un message à une application qui ne répond plus. Car le message ne sera jamais traité et votre application se bloquera elle aussi à son tour.
  • PostMessage : Cette fonction est, elle, asynchrone. En d'autres mots, elle s'occupe simplement de placer le message dans la queue des messages à traiter et retourne immédiatement. Elle ne se préoccupe donc pas de savoir si le message a été correctement traité.
  • SendMessageCallback : Cette fonction, dérivée de SendMessage, retourne, elle, immédiatement. Mais elle vous permet de spécifier l'adresse d'une fonction de "rappel" qui sera appelée lorsque le message aura été traité.
  • SendMessageTimeout : Cette fonction, aussi dérivée de SendMessage, a un comportement synchrone, mais vous permet de spécifier un "timeout". C'est-à-dire une durée limite après laquelle la fonction retourne automatiquement même si le message n'a pas encore été traité.

Il existe encore d'autres API permettant d'envoyer des messages, tel que PostThreadMessage ou SendNotifyMessage. Vous trouverez leur description dans la MSDN : Messages and Message Queues.

Vous aurez remarqué que la recherche de la fenêtre nécessite que l'on connaisse son titre complet. Si vous désirez rechercher une fenêtre sur base d'une partie de son titre, il vous faudra procéder différemment. A savoir, énumérer toutes les fenêtres et comparer leur titre avec le vôtre. Vous trouverez l'implémentation d'une telle fonction sur VBnet : Finding Applications Matching a Specific Class or Window Title.

Concernant la fermeture d'application externe, vous pouvez aussi consulter la fiche suivante : 176391 - HOWTO: Programmatically Close a Single Instance of a Windows-Based Program.

Date de publication : 26 janvier 2003
Dernière modification : 26 janvier 2003
Rubriques : API, Windows
Mots-clés : fermer, quitter, FindWindow, SendMessage, PostMessage, WM_CLOSE