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 :

Passer pointeur via message à autre prog


Sujet :

C++Builder

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    162
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Mai 2002
    Messages : 162
    Points : 88
    Points
    88
    Par défaut Passer pointeur via message à autre prog
    j'avais un problème : mon programme se lançait plusieurs fois lorsque l'on sélectionnait plusieurs fichiers dans l'explorateur et qu'on appuyait sur "Entrée".

    Ca c'est résolu.

    MAIS

    j'aimerai que les autres instances du programme, avant de se fermer, envoient leurs paramètres au programme déjà lancé.

    J'ai donc mis en place un petit message : WM_ADDFILE
    en me disant que je pourrais mettre en wParam un pointeur sur la chaine de paramètres.

    non.

    ça ne fonctionne pas.

    Pour voir j'ai essayé de passer juste un pointeur sur un entier, ça donne ça :

    dans le WinMain :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #define WM_ADDFILE  (WM_USER + 2005)
     
    ...
     
        int* pMsg;
        pMsg = new int;
     
        AnsiString s = (int)pMsg;    //on affiche l'adresse pointée
        MessageBox(NULL, s.c_str(), "toto", MB_OK);
     
        PostMessage(hPreviousInstance, WM_ADDFILE, (WPARAM)pMsg, NULL);
    et dans la méthode OnMessage d'un TApplicationEvents:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
        if (Msg.message == WM_ADDFILE)
        {
            if (*( (int*)Msg.wParam ) == 24)
                MessageBox(NULL, "message24", "titi", MB_OK);
            else
                MessageBox(NULL, "echec24", "titi", MB_OK);
     
            delete (int*)Msg.wParam;
            Handled = true;
        }
    la valeur de wParam correspond bien à l'adresse pointée pas pMsg mais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    *( (int*)Msg.wParam )
    vaut "????"

    euh... pourquoi ?
    quelle autres solutions pour passer les paramètres du programme au programme déjà présent ?


    [Modération, Alacazam : Prière d'utiliser un langage correct, merci]

  2. #2
    Membre habitué Avatar de ken_le_videur
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 129
    Points : 145
    Points
    145
    Par défaut
    Utilise SendMessage() à la place de POstMessage(). PostMessage() ne doit pas être utilisée avec des pointeurs.

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    162
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Mai 2002
    Messages : 162
    Points : 88
    Points
    88
    Par défaut
    mais SendMessage n'est pas réceptionné par mon TApplicationEvents ...

    Je crois que j'avais essayé de mettre le message dans un BEGIN_MASSAGE_MAP END_MESSAGE_MAP mais il n'a pas été reçu non plus

    je réessaie et je vous informe...

  4. #4
    Membre habitué Avatar de ken_le_videur
    Profil pro
    Inscrit en
    Juillet 2002
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2002
    Messages : 129
    Points : 145
    Points
    145
    Par défaut
    A priori, l'utilisation de l'un ou de l'autre ne crée aucune différence pour l'application receptrice. La différence se situe au niveau de l'application emettrice.

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    162
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Mai 2002
    Messages : 162
    Points : 88
    Points
    88
    Par défaut
    ah là là...

    je n'y comprends rien.

    j'ai dans l'ordre :

    dans mon main :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #define WM_ADDFILE (WM_USER + 2005)
     
     
    WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
    {
      ...
                SendMessage(hPreviousInstance, WM_ADDFILE, (WPARAM)pMsg, NULL);
      ...
    pour envoyer le message WM_ADDFILE à l'instance précédente de mon programme.

    dans mon MainForm.h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #define WM_ADDFILE (WM_USER + 2005)
    ...
    protected:
        BEGIN_MESSAGE_MAP
            //Pour le drop de fichiers
            VCL_MESSAGE_HANDLER(WM_DROPFILES, TMessage, WMDropFiles);
            //Pour l'ajout de fichier quand il y plusieurs instances 
            VCL_MESSAGE_HANDLER(WM_ADDFILE,   TMessage, WMAddFile);
        END_MESSAGE_MAP(TForm)
     
    private:
        virtual void __fastcall WMDropFiles(TMessage &Message);
        virtual void __fastcall WMAddFile(TMessage &Message);
    et ma fonction WMAddFile qui est la même que le OnMessage du feu TApplicationEvents

    et bien devinez... je ne rentre jamais dans WMAddFile.
    alors que si dans le WinMain je mets
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SendMessage(hPreviousInstance, WM_CLOSE, NULL, NULL);
    la fenêtre se ferme. Donc le message est bien envoyé, mais pas reçu ?

    le DropFile fonctionne bien par contre. Ca viendrait peut-être de la définition de WM_ADDFILE ?

  6. #6
    Membre régulier
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    162
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Mai 2002
    Messages : 162
    Points : 88
    Points
    88
    Par défaut
    Bon, alors deux possibilités : Personne ne me répond car

    - tout les utilisateurs du forum sont en train de plancher sur mon problème et personne ne trouve de solution.
    - tout le monde me fait la gueule parce que j'ai dit que j'aimais bien jumelle.

    (Optons pour la première possibilité...)

    Réjouissez-vous, j'ai trouvé une solution. Ca m'a l'air d'être du bidouillage mais ça fonctione....

    Premièrement : on ne passe pas de pointeur à un autre prog car windows leur attribue des espaces mémoire séparés. Donc c'est un échec. Il faut utiliser des segments de mémoire partagée.

    Deuxièmement : Les messages étaient reçus n'importe comment car ils étaient envoyés à l'application et non pas à la fenêtre principale. L'application voyant WM_CLOSE se fermait (normal) mais elle n'envoyait pas WM_ADDFILE aux fenêtres. Le problème est résolu en retrouvant la fenêtre principale déjà présente plutôt que l'application et en lui envoyant les messages.

    Je vous explique ma méthode : Lors du lancement du prog je crée un segment de mémoire partagée. Lorsqu'une autre instance est lancée, elle essaie de créer un segment de mémoire partagée, mais échoue. Ca nous permet de savoir que le prog est déjà lancé. Que fait-elle alors ? elle retrouve le segment déjà existant, prend ses fichiers en paramètres et pour chaque fichier elle dis à l'application déjà lancée "tiens, je te file mon fichier" et elle écrit le chemin d'accès au fichier dans le segment partagé. Et voilà !

    bon, un peu de détails : Mon prog est un visualiseur d'images. lorsque dans l'explorateur vous sélectionnez n fichiers et faites "entrée", le programme est lancé n fois. Maintenant n-1 programmes filent leur paramètre au dernier programme :

    Dans le fichier main :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
     
    #define WM_ADDFILE      (WM_USER    + 2010)
    #define WM_ADDFILESTART (WM_ADDFILE +   10)
    #define FILEMAPPINGNAME "VieuxVerFileMapping_"
     
    //---------------------------------------------------------------------------
    void __fastcall SendFileToPrevious(HANDLE hFileMap)
    {
        //on retrouve l'instance précédente
        //ATTENTION : les messages seront passés à la fiche principale et non pas à l'application
        //donc il faut retrouver la fiche principale
        HWND hPreviousInstance = FindWindow( "TMainFormFrm", NULL);
     
        if (hPreviousInstance)    //c'est cool, on l'a trouvée
        {
            //On retrouve la mémoire partagée
            char* pFile = (char*)MapViewOfFile(hFileMap, FILE_MAP_WRITE, 0, 0, 0);
     
            int i = 1;
     
            //on file tous les fichiers.
            while (ParamStr(i) != "")
            {   
                //attendre que les fichiers précédents aient étés traités avant d'écrire en mémoire
                //VOIR (*)
                SendMessage(hPreviousInstance, WM_ADDFILESTART, 0, 0);
     
                strcpy(pFile, ParamStr(i).c_str());	//écrit le nom du fichier dans la mémoire partagée
                SendMessage(hPreviousInstance,	//dire à l'instance précédente qu'il y a un fichier
                    WM_ADDFILE,
                    (WPARAM)( ( ((DWORD)hFileMap) & 0xFFFF0000 ) >> 16 ),	//heu je ne me rappelle plus de la taille des (W/L)Param
                    (LPARAM)(   ((DWORD)hFileMap) & 0xFFFF)    );		//alors je passe deux octets du handle du fichier sur chaque
     
                i++;
            }
     
            UnmapViewOfFile(hFileMap);
        }
    }
     
    //---------------------------------------------------------------------------
    WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
    {
        Application->Title = APPNAME;
     
        //on crée le segment de mémoire partagée
        HANDLE hFileMap = CreateFileMapping((HANDLE)0xFFFFFFFF, NULL, PAGE_READWRITE,
                     0, MAX_PATH, FILEMAPPINGNAME);
     
        if (GetLastError() == ERROR_ALREADY_EXISTS) //le programme est déjà lancé
        {
            if (ParamStr(1) != "")	//allez hop, on file les fichiers au prog
                SendFileToPrevious(hFileMap);
     
            return 0;
        }
     
        try
        {
             //... initialisation de l'appli
        }
        catch (Exception &exception)
        {
             Application->ShowException(&exception);
        }
        catch (...)
        {
             //...
        }
     
        //Penser à fermer le fichier avant de partir
        CloseHandle(hFileMap);
        return 0;
    }
    (*) ceci est du bidouillage mais ça aide bien :
    Le programme auquel on envoie les messages traite ces messages un par un. normal.
    Rappelons que SendMessage bloque le programme appelant tant que le message n'a pas été traité (contrairement à PostMessage).
    Comme indiqué plus loin, WM_ADDFILESTART ne fait rien. Disons que nous ne l'utilisions pas :
    Chaque nouvelle instance du programme va écrire dans le segment mémoire.

    Le programme appelé reçoit les messages :
    WM_ADDFILE fichier1
    WM_ADDFILE fichier2
    WM_ADDFILE fichier3
    WM_ADDFILE fichier4

    le problème est que les messages seront envoyés avant même qu'il ait fini de traiter le premier fichier. Donc pour les trois autres messages il lira "fichier4"

    Maintenant avec le WM_ADDFILESTART :
    WM_ADDFILESTART
    WM_ADDFILE fichier1
    WM_ADDFILESTART
    WM_ADDFILE fichier2
    WM_ADDFILESTART
    WM_ADDFILE fichier3
    WM_ADDFILESTART
    WM_ADDFILE fichier4

    Chaque application envoie son WM_ADDFILESTART. Le prog appelé reçoit le premier fichier. Il s'en occupe. Pendant ce temps, une autre appli lui envoie WM_ADDFILESTART. Mais comme l'appelé est trop occupé par le traitement du premier fichier, il ne repond pas tout de suite, il répondra quand il aura fini.
    Donc, exactement ce qu'on voulait, tant que l'appelant ne reçoit pas de réponse à son WM_ADDFILESTART, il attend... et pendant ce temps là il n'écrit pas en mémoire partagée !!!

    Alors là on est content, ça roule !

    pour ce qui est du traitement des messages :

    dans le .h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    //... des trucs
    private:
        virtual void __fastcall WMAddFile(TMessage &Message);
        virtual void __fastcall WMAddFileStart(TMessage &Message) {};	//fonction qui ne fait rien
     
    public:
        BEGIN_MESSAGE_MAP
            //Pour initialiser l'ajout de fichier quand il y plusieurs instances
            VCL_MESSAGE_HANDLER(WM_ADDFILESTART,   TMessage, WMAddFileStart);
            //Pour l'ajout de fichier quand il y plusieurs instances
            VCL_MESSAGE_HANDLER(WM_ADDFILE,   TMessage, WMAddFile);
        END_MESSAGE_MAP(TForm);
    dans le .cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
     
    void __fastcall TMainFormFrm::WMAddFile(TMessage &Message)
    {
        //reconstruire le handle
        HANDLE hFile = (HANDLE) (
                &#40; &#40;&#40;DWORD&#41;Message.WParam&#41; << 16 &#41;
                |
                &#40; &#40;DWORD&#41;Message.LParam &#41;
                                &#41;;
     
        if &#40;hFile&#41;
        &#123;
    	//on récupère le segment de mémoire
            char* pFile = &#40;char*&#41;MapViewOfFile&#40;hFile, FILE_MAP_READ, 0, 0, 0&#41;;
     
            if &#40;pFile&#41;
            &#123;
                char sPath&#91;MAX_PATH&#93;;
                strcpy&#40;sPath, pFile&#41;;
     
                //on ajoute l'image à la liste déjà présente
                m_iImageIndex = g_pSlideManager->Count&#40;&#41;;
                g_pSlideManager->AddSlide&#40;sPath&#41;;
                SetSlide&#40;&#41;;
     
                UnmapViewOfFile&#40;hFile&#41;;
            &#125;
        &#125;
     
        //on met l'application au premier plan
        Application->BringToFront&#40;&#41;;
    &#125;
    voilà, j'espère que ça pourra aider des gens !!

  7. #7
    Nouveau Candidat au Club
    Inscrit en
    Juillet 2003
    Messages
    1
    Détails du profil
    Informations forums :
    Inscription : Juillet 2003
    Messages : 1
    Points : 1
    Points
    1
    Par défaut petit rectificatif
    salut,

    j'ai essayé ton code qui m'a vraiment rendu service, merci
    mais j'ai deux petites remarques :

    1. la taille des L/W param est de au moins 32bits (j'ai passé 0x123456789) donc on peut alléger à peine le code

    2. pour le WM_ADDFILESTART, en fait je crois que ça ne se passe pas tout à fait comme tu le dis :

    la 1° app. envoie son AddFileStart, puis écrit et envoie AddFile
    la 2° app. envoie son AddFileStart puis attend
    la 3° app. envoie son AddFileStart puis attend
    le traitement du premier fichier est fini, l'application mère répond immédiatement aux deux AddFileStart
    les 2 app. reçoivent la notification quasi simultanément
    les 2 app. écrivent en mémoire quasi simultanément
    les 2 app. envoie leur AddFile quasi simultanément
    l'application mère traite deux AddFile avec la même chose dans la mémoire

    Donc en tout cas c'est ce qu'il se passe chez moi, mais si ça marche chez toi redis-moi, si j'ai fait une erreur en recopiant ...
    Enfin moi je n'ai pas vraiment besoin de cette fonctionnalité mais bon, ça m'intrigue quand même ...

    cyril

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 02/07/2014, 13h16
  2. Réponses: 4
    Dernier message: 01/02/2013, 17h05
  3. Réponses: 2
    Dernier message: 01/02/2013, 16h50
  4. Commander d'autres prog via VB
    Par d.jphilippe dans le forum Windows Forms
    Réponses: 11
    Dernier message: 20/08/2008, 00h20
  5. [statusbar] recuperer des infos d'un autre prog
    Par noyax dans le forum API, COM et SDKs
    Réponses: 2
    Dernier message: 20/12/2002, 16h52

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