IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++Builder Discussion :

Send/PostMessage problème de handle


Sujet :

C++Builder

  1. #1
    Nouveau membre du Club

    Profil pro
    Inscrit en
    Juin 2005
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 17
    Points : 25
    Points
    25
    Par défaut Send/PostMessage problème de handle
    Bonjour,

    J'ai une application qui de temps en temps doit couper le son de l'ordinateur. La seule méthode que j'ai trouvée pour l'instant est d'ouvrir sndvol32.exe et de lui envoyer le message Alt + M, qui le passe en muet. (Déjà c'est une méthode que je trouve moyennement propre).

    Donc le but du jeu est d'ouvrir une fenêtre (sndvol32.exe), de lui envoyer un message et de fermer la dite fenêtre.
    Pour ouvrir la fenêtre pas de problème : 3 solutions CreateProcess, ShellExecuteEx ou ShellExecute.
    Pour la fermer, ca ne fonctionne que si elle a été ouverte avec l'une des 2 premières fonctions. TerminateProcess fonctionne très bien (avec le handle que la fonction de création me retourne).

    Le problème c'est pour lui envoyer ce fameux message. 2 fonctions pour cela : PostMessage ou SendMessage, mais toutes les 2 ne fonctionnent pas et me disent tres gentillement que le handle de ma fenêtre n'est pas valide
    (Enfin gentillement, c'est façon de parler, il faut quand même appeler la fonction GetLastError suivie de FormatMessage, pour comprendre ce qu'il s'est passé).

    Pour info le handle est retourné par la fonction de création alors je ne vois pas pourquoi il serait pas valide! Surtout que TerminateProcess, lui, fonctionne.

    Donc voilà, je désespère et j'ai besoin de votre aide.

    Merci

  2. #2
    Membre du Club
    Profil pro
    Inscrit en
    Février 2004
    Messages
    44
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2004
    Messages : 44
    Points : 52
    Points
    52
    Par défaut
    Bonjour,

    En fait, la fonction CreateProcess crée un Handle sur l'application.
    Les fonctions PostMessage ou SendMessage utilisent un Handle sur la fenêtre de l'aplication qui doit recevoir le message. --> le message Handle non valide.
    Il te faut obtenir le Handle de la fenêtre de l'application. Pour cela regarde dans les fonctions API de Windows, je crois que la fonction à utiliser est FindWindow.

    J'espère que ces informations te seront utiles.

  3. #3
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 50
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Et si tu utilisais plutôt l'API de gestion du son, à la place ? Hmm ? ;-)

    http://support.microsoft.com/default.aspx?scid=kb;en-us;139098
    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/multimed/htm/_win32_waveoutsetvolume.asp

    Je trouve ça un peu plus propre, moi...

  4. #4
    Nouveau membre du Club

    Profil pro
    Inscrit en
    Juin 2005
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 17
    Points : 25
    Points
    25
    Par défaut
    carrément que c'est plus propre!!! C'est exactement la fonction que je cherchais! Pourquoi personne n'en parle jamais? :-)
    Enfin merci beaucoup, cette méthode me plait bien et en plus elle fonctionne :-)
    Bon ca n'empeche que je risque d'avoir besoin de résoudre le problème du Post/SendMessage parce que je risque d'en avoir besoin pour la suite. Donc je vais voir du côté de FindWindow mais je trouve bizarre qu'on ne puisse pas récupérer le handle de fenêtre a partir du handle de programme...

  5. #5
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 50
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par bibmari
    Pourquoi personne n'en parle jamais? :-)
    Peut-être parceque personne sur le forum ne l'a encore demandé... Mets une p'tite réponse (avec au moins le lien vers ce topic, voire le bout de code lui-même) sur ce topic, je pense que ce sera le plus rapide pour que ça soit intégré dans la FAQ... D'ailleurs, à mon avis, ce serait même la FAQ Win32 qui devrait être ciblée.

    Citation Envoyé par bibmari
    Enfin merci beaucoup, cette méthode me plait bien et en plus elle fonctionne :-)
    Vaudrait mieux, c'est ce qu'utilise "SndVol32.exe" pour régler le volume !!

    Citation Envoyé par bibmari
    je trouve bizarre qu'on ne puisse pas récupérer le handle de fenêtre a partir du handle de programme...
    Non, car un exécutable possédant une fenêtre peut être "repéré" au minimum par :
    - Son PID,
    - Un handle sur le processus,
    - Le ThreadID de son thread principal,
    - Un handle sur ce thread principal,
    - Un handle sur la fenêtre principale.
    Ca fait beaucoup de références possibles... ;-) Tu utilises celle dont tu as besoin, mais effectivement, FindWindows permet de récupérer un handle de fenêtre. Sinon, tu as la possibilité de passer par EnumWindows et/ou EnumProcesses, si ma mémoire est bonne.

    Histoire de finir le topic, pense à poster le code que tu as utilisé (pour ceux qui liraient le topic en ayant le même problème que toi), et pense à cliquer sur en bas à gauche ! ;-)

  6. #6
    Nouveau membre du Club

    Profil pro
    Inscrit en
    Juin 2005
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 17
    Points : 25
    Points
    25
    Par défaut
    désolée de te décevoir mais j'ai l'impression que ce post n'est pas encore clos :-)

    J'ai voulu faire un test tout simple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SendMessage(Form1->Handle,WM_QUIT, 0, 0);
    Sachant que j'ai bien vérifié que Form1->Handle est un HWND, comme dit si bien la doc de Borland :

    Donne accès à l'objet écran Windows sous-jacent au contrôle.
    __property HWND Handle = {read=GetHandle, nodefault};

    Et la, plus d'erreur GetLastError me retourne bien 0, mais il ne se passe rien.
    Une idée? Qu'est ce que j'ai fait de mal ? :-)

  7. #7
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 50
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par bibmari
    Et la, plus d'erreur GetLastError me retourne bien 0, mais il ne se passe rien.
    Ca veut juste dire que ton message a bien été transmis, donc qu'il y avait bien une boucle de message de l'autre côté.

    Citation Envoyé par bibmari
    Une idée? Qu'est ce que j'ai fait de mal ? :-)
    Rien, mais il faut que la boucle de messages du window ciblé sache traiter les messages WM_QUIT, tout simplement !! Essaie avec WM_CLOSE, mais ça ne fermera peut-être pas le processus lui-même (ça dépend si c'est la fiche principale ou pas, si elle termine l'application à sa fermeture, etc.)

    En BCB/Delphi, tu vas utiliser Application->Handle, plutôt... Pour des exécutables non-VCL, il faut récupérer le HWND principal, mais de tête, j'avoue que je ne sais plus comment on fait... Je ne me sers jamais de ce genre de trucs, en fait !!

  8. #8
    CGi
    CGi est déconnecté
    Expert éminent
    Avatar de CGi
    Inscrit en
    Mars 2002
    Messages
    1 050
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 1 050
    Points : 8 273
    Points
    8 273
    Par défaut
    J'ai voulu faire un test tout simple :

    Code:
    SendMessage(Form1->Handle,WM_QUIT, 0, 0);
    Fait un PostMessage tu va voir la différence

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    PostMessage(Form1->Handle,WM_QUIT, 0, 0);
    SendMessage est envoyé à la procédure de fenêtre et
    ne passe pas par la boucle de message.

  9. #9
    Nouveau membre du Club

    Profil pro
    Inscrit en
    Juin 2005
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 17
    Points : 25
    Points
    25
    Par défaut
    Ok j'ai compris la différence. Avec WM_CLOSE ca marche.
    Merci beaucoup.
    Si on en revient à mon exemple du tout début :
    Je crée ma fenêtre comme ca :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    SHELLEXECUTEINFO ExecuteInfo;
       memset(&ExecuteInfo, 0, sizeof(ExecuteInfo));
     
       ExecuteInfo.cbSize       = sizeof(ExecuteInfo);
       ExecuteInfo.hwnd         = Form1->Handle;
       ExecuteInfo.lpVerb       = "open";
       ExecuteInfo.lpFile       = "sndvol32.exe";
       ExecuteInfo.lpDirectory  = 0;
       ExecuteInfo.lpParameters = 0;
       ExecuteInfo.nShow        = SW_SHOW;
       ExecuteInfo.hInstApp     = 0;
       ExecuteInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
       ShellExecuteEx(&ExecuteInfo);
    Ensuite je récupére le handle de fenêtre (ici c'est assez simple vu que la fenêtre appartient à Form1 :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    HWND h = GetWindow(Form1->Handle, GW_OWNER);
    Mais si par exemple je veux lui donner le focus
    Il ne se passe rien, tous les messages que je tente de lui envoyer (WM_KEYDOWN, WM_SYSKEYDOWN ...) ne font rien, sauf WM_CLOSE.

    Donc même si je ne vais pas utiliser cette fonction, je me demande si je n'ai pas fait quelquechose de travers :-)

    Encore Merci a Mac LAK pour s'interesser à mon problème :-)

  10. #10
    Nouveau membre du Club

    Profil pro
    Inscrit en
    Juin 2005
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 17
    Points : 25
    Points
    25
    Par défaut
    Merci CGI, c'est magique :-)

    Il me reste ce problème avec SetFocus. Pourquoi est ce que ca ne marche pas alors que j'ai quand même le bon handle cette fois-ci? :-)
    Une idée?

    Ceci dit, je n'en ai plus besoin pour le moment mais je n'aime pas les problèmes non résolus :-)

  11. #11
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 50
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par bibmari
    Pourquoi est ce que ca ne marche pas alors que j'ai quand même le bon handle cette fois-ci? :-)
    Une idée?
    Là, de tête, non... Par contre, je sais qu'une fois j'ai pas mal peiné pour simplement me rendre compte que je tapais dans un mauvais handle (non héritable => invalide dans le child), tu devrais peut-être regarder de ce côté... Ou essayer CreateProcess à la place de ShellExecuteEx.

    Tu tiens au courant ?

  12. #12
    Membre du Club
    Profil pro
    Inscrit en
    Février 2004
    Messages
    44
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2004
    Messages : 44
    Points : 52
    Points
    52
    Par défaut
    Je crois que pour SetFocus, c'est le handle fenêtre du "composant" qu'il faut utiliser et pas le handle de la fenêtre à qui appartient le composant,

    Si tu veux utiliser SetFocus sur edit1 (TEdit) tu dois utiliser edit1->Handle

  13. #13
    Nouveau membre du Club

    Profil pro
    Inscrit en
    Juin 2005
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 17
    Points : 25
    Points
    25
    Par défaut
    Mac LAK : j'ai essayé avec CreateProcess et même problème :-)
    Sinon je pense pas que ce soit une histoire d'héritage, puisque je crée le processus et juste derriere j'essaie de me servir du handle, dans la même méthode du même objet.

    mduse : ok avec un TEdit ca fonctionne mais si tu veux faire un SetFocus sur la calculatrice par exemple, avec FindWindow tu récupère un handle mais SetFocus ne fonctionne pas mais pas d'erreur :-)

    voici mon code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    HWND h = FindWindow(NULL, "Calculatrice");
    ::SetFocus(h);
    Merci de votre aide.

  14. #14
    CGi
    CGi est déconnecté
    Expert éminent
    Avatar de CGi
    Inscrit en
    Mars 2002
    Messages
    1 050
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 1 050
    Points : 8 273
    Points
    8 273
    Par défaut
    Je ne crois pas qu'on puisse mettre le premier paramètre de FindWindow
    à NULL (C'est le nom de la classe de fenêtre).

  15. #15
    Nouveau membre du Club

    Profil pro
    Inscrit en
    Juin 2005
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 17
    Points : 25
    Points
    25
    Par défaut
    ok mais alors ... ou on le trouve ce fameux nom de classe de fenetre? :-)

  16. #16
    CGi
    CGi est déconnecté
    Expert éminent
    Avatar de CGi
    Inscrit en
    Mars 2002
    Messages
    1 050
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 1 050
    Points : 8 273
    Points
    8 273
    Par défaut
    ok mais alors ... ou on le trouve ce fameux nom de classe de fenetre?
    Celui de la calculatrice est SciCalc
    Tu peut les avoir avec l'utilitaire fourni avec c++Builder WinSight32

  17. #17
    Nouveau membre du Club

    Profil pro
    Inscrit en
    Juin 2005
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 17
    Points : 25
    Points
    25
    Par défaut
    ok merci.

    Pour info, WinSight n'est pas disponible sur la version personnelle de Borland C++Builder :-)

    Sinon j'ai donc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
       HWND h = FindWindow("SciCalc", NULL);
       ::SetFocus(h)
    h n'est pas NULL donc FindWindow semble fonctionner correctement
    mais SetFocus ne fonctionne pas, ma calculatrice est toujours en arrière plan.

    Merci

  18. #18
    CGi
    CGi est déconnecté
    Expert éminent
    Avatar de CGi
    Inscrit en
    Mars 2002
    Messages
    1 050
    Détails du profil
    Informations forums :
    Inscription : Mars 2002
    Messages : 1 050
    Points : 8 273
    Points
    8 273
    Par défaut
    Pour passer au premier plan une fenêtre de premier niveau on utilise
    SetForegroundWindow


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
        HWND hcalc;
        hcalc = FindWindow("SciCalc", NULL);
        SetForegroundWindow(hcalc);
    Aprés vérification on peut utiliser le titre de la fenêtre seul avec FindWindow,
    mais on est jamais sûr du titre.

  19. #19
    Nouveau membre du Club

    Profil pro
    Inscrit en
    Juin 2005
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 17
    Points : 25
    Points
    25
    Par défaut
    Ca y est j'ai réussi :-) !!!! Après tant de galères :-)
    Bon alors voilà ce que j'ai fait :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
       HWND h = FindWindow("SciCalc", NULL);
       SetForegroundWindow(h);
       PostMessage(h, WM_KEYDOWN, 0x52, 0);
       PostMessage(h, WM_KEYUP, 0x52, 0);
    Pour fonctionner le PostMessage a besoin du code ASCII de la touche appuyée, ici R (qui donne l'inverse du nombre dans la calculatrice).

    Merci a tous.

    Pour info pour avoir le nom de la classe, j'ai trouvé un soft tres tres bien (qui ne fait pas que ca bien sur) et qui permet aussi d'envoyer des messages à la main ...
    Il s'appelle MyCatch : http://www.artoflog.com/logiciels/freewares/mycatch/mycatch.htm

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [GUIDE] problème de handles
    Par El_bennito dans le forum Interfaces Graphiques
    Réponses: 7
    Dernier message: 03/07/2009, 12h02
  2. Problème création handle
    Par maicheul dans le forum Débuter
    Réponses: 6
    Dernier message: 16/06/2009, 22h04
  3. Problème de handles
    Par Zhitoune dans le forum Interfaces Graphiques
    Réponses: 5
    Dernier message: 18/12/2008, 15h47
  4. problème de handle dans le callback d'un bouton
    Par ZeFMG dans le forum Interfaces Graphiques
    Réponses: 3
    Dernier message: 04/11/2008, 11h48
  5. GUI & Timer => problème d'handle sur la figure
    Par wintereivax dans le forum Interfaces Graphiques
    Réponses: 10
    Dernier message: 13/01/2008, 21h20

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo