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

MFC Discussion :

Modification de la "message map" à l'execution ?


Sujet :

MFC

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 7
    Points : 5
    Points
    5
    Par défaut Modification de la "message map" à l'execution ?
    Bonjour,

    Je suis nouveau sur le forum... il est probable que le sujet ai été débattu, mais la fonction de recherche ne m'a pas permi de cerner rapidement un nombre suffisament restreint de fil à lire. Alors je soumets mon probleme :

    Je souhaite modifier un handler (en fait substituer un handler par un autre, du même type) lors de l'excution d'un programme. Celui-ci est developpé avec VS 2005 en utilisant les MFC.

    D'après ce que j'ai pu constater, la table des messages MFC est faite pour être statique. Mais j'ai également vu sur le net que des "workaround" était possible... seulement, plusieurs solutions tendent vers la reécriture d'un framework autorisant les tables dynamiques - too much pour moi.

    Je veux seulement, pour un message en particulier, pouvoir remplacer un Handler_A associé à ce message par un Handler_B :
    Soit une classe CTestAppDialog dérivant de CDialog,
    Soit un message ON_EVENEMENT (n'importe quoi, un clic souris, une frappe clavier), on lui associe un Handler OnEvenementProcess_A() dans le
    MESSAGE_MAP. Puis on souhaite remplacer, a l'exécution, OnEvenementProcessType_A() par OnEvenementProcessType_B() dans la table.
    Comme il s'agit,finalement de pointeurs sur fonction (quelque part dans les structures complexes genre AFX_MSGMAP_ENTRY) ca devrait être possible.

    Alors comment faire simplement ?
    Merci d'avance
    Bernard

  2. #2
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Bonjour et bienvenu,
    Je dirais à priori que c'est une mauvaise idée de vouloir trifouiller dans les structures internes des MFC. Rien ne te garantie une pérennité et tu risques de passer plus de temps en 'bidouille' qu'autre chose. Plusieurs solutions:
    -> Sublcasser ta fenêtre ()
    -> Récupérer le message dans un OnEvenementProcess qui ensuite invoque OnEvenementProcess_A ou OnEvenementProcess_B via un mécanisme interne que tu mets en place (pointeur de fonction, état, foncteur...).

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 7
    Points : 5
    Points
    5
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    Je dirais à priori que c'est une mauvaise idée de vouloir trifouiller dans les structures internes des MFC. Rien ne te garantie une pérennité et tu risques de passer plus de temps en 'bidouille' qu'autre chose.
    D'accord avec cela, mais c'est une action "one shoot", pour un developpement particulier, qui n'aura probalement pas de réutilisation ailleurs.

    Citation Envoyé par 3DArchi Voir le message
    -> Récupérer le message dans un OnEvenementProcess qui ensuite invoque OnEvenementProcess_A ou OnEvenementProcess_B via un mécanisme interne que tu mets en place (pointeur de fonction, état, foncteur...).
    En fait, c'est ce que je voulais eviter, car quelque soit le mécanisme, il y a une indirection (un test, l'appel d'une fonction, ...). Je souhaitais changer le pointeur sur fonction pour embrayer sur le bon handler dès reception du message, l'application est critique en temps de calcul, le handler en question est apellé environ 100 x par seconde.

    Les evenements proviennent d'un ActiveX, et la "message map" à modifier est "EVENTSINK_MAP". En fait, j'arrive à décripter la table, mais je ne peux pas modifier le pointeur sur fonction. Il me semble que les macros MFC "DECLARE_EVENTSINK_MAP", "BEGIN_EVENTSINK_MAP", etc... utilisent partout le mot clé "const". Mes tentatives de modification de la table se soldent par un "0xC0000005: Violation d'accès lors de l'écriture" :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    AFX_EVENTSINKMAP_ENTRY* my_pMap = (AFX_EVENTSINKMAP_ENTRY*)this->eventsinkMap.lpEntries;
     
    // itération à l'interieur de la table des message
    if(my_pMap[i].dispEntry.lDispID == 5 ) // c'est la liaison event-handler que je souhaite modifier
        my_pMap[i].dispEntry.pfn = (AFX_PMSG)&CTestAppDlg::OnNouveauHandler; 
    // ici ca plante : 0xC0000005: Violation d'accès lors de l'écriture
    Il me semblait que "const" servait de verification lors de la compilation ?
    Or le code compile sans erreurs ... mais génére une erreur lors de l'accès à l'écriture lors de l'execution. Bizzare !

    Any hints ?
    Bernard

  4. #4
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Bon, j'ai retrouvé la définition de BEGIN_EVENTSINK_MAP :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #define BEGIN_EVENTSINK_MAP(theClass, baseClass) \
        const AFX_EVENTSINKMAP* PASCAL theClass::_GetBaseEventSinkMap() \
            { return &baseClass::eventsinkMap; } \
        const AFX_EVENTSINKMAP* theClass::GetEventSinkMap() const \
            { return &theClass::eventsinkMap; } \
        const AFX_EVENTSINKMAP theClass::eventsinkMap = \
            { &theClass::_GetBaseEventSinkMap, &theClass::_eventsinkEntries[0], \
                &theClass::_eventsinkEntryCount }; \
        UINT theClass::_eventsinkEntryCount = (UINT)-1; \
        const AFX_EVENTSINKMAP_ENTRY theClass::_eventsinkEntries[] = \
        { \
    Effectivement, le const ici veut dire aussi que le tableau n'étant pas modifiable dynamiquement, il sera placé dans une zone de données en lecture seule. Le système interdit l'écriture sur cette zone mémoire. Conclusion : tu ne peux pas modifier une entrée de ce tableau.


    Citation Envoyé par BB_17 Voir le message
    le handler en question est apellé environ 100 x par seconde.
    Pas sur que le coût d'une indirection soit si critique par rapport à ce que fait ta fonction...

  5. #5
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 382
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 382
    Points : 41 590
    Points
    41 590
    Par défaut
    Un truc que tu pourrais faire, c'est contourner les macros BEGIN_MESSAGE_MAP, DECLARE_MESSAGE_MAP etc. pour créer ta propre implémentation de la fonction virtuelle GetMessageMap(), et en faire une fonction qui retourne une copie modifiable de la map. Cette copie pourrait être créée dans le constructeur de ta classe à partir de la vraie message map statique...

  6. #6
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 7
    Points : 5
    Points
    5
    Par défaut
    Merci à 3DArchi pour avoir confirmé mes soupçons.

    Citation Envoyé par Médinoc Voir le message
    Un truc que tu pourrais faire, c'est contourner les macros BEGIN_MESSAGE_MAP, DECLARE_MESSAGE_MAP etc. pour créer ta propre implémentation de la fonction virtuelle GetMessageMap(), et en faire une fonction qui retourne une copie modifiable de la map. Cette copie pourrait être créée dans le constructeur de ta classe à partir de la vraie message map statique...
    Oui mais je ne me sens pas assez costaud en C++/MFC pour faire cela, et on se rapproche de la reecriture d'un framework. En faisant des recherches j'étais tombé sur :
    http://blog.emmanueldeloget.com/inde...remiere-partie
    Avec une implementation de table de message dynamique.

    Et puis je trouve étrange que ce genre de code (re-écritude de GetMessageMap()) ne traine pas sur le net... Les developpeurs utilisant les pointeurs sur fonction et les fans de Qt (avec connect(signal,slot)) on surement dû avoir envie de contourner les tables statiques.
    A mon avis, ca doit être assez complexe.

    Je pense que je vais laisser tomber et utiliser une indirection supplementaire (un pointeur sur fonction à moi, dans un handler unique)

    On peut toutefois laisser le sujet ouvert quelque temps, we never know !!!!!

    Bernard

  7. #7
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 382
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 382
    Points : 41 590
    Points
    41 590
    Par défaut
    Pour moi, c'est pourtant simple: Tu regardes les macros, puis tu fais la même chose en coupant les bouts qui te gênent...
    S'il y a un moyen d'obtenir la taille d'une message map (et il y en a forcément un), alors il est aisé de la dupliquer dans ton constructeur, et mémoriser un pointeur vers elle en variable membre. Ensuite, il suffit de faire une fonction qui retourne ce pointeur.

  8. #8
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Pour moi, c'est pourtant simple: Tu regardes les macros, puis tu fais la même chose en coupant les bouts qui te gênent...
    S'il y a un moyen d'obtenir la taille d'une message map (et il y en a forcément un), alors il est aisé de la dupliquer dans ton constructeur, et mémoriser un pointeur vers elle en variable membre. Ensuite, il suffit de faire une fonction qui retourne ce pointeur.
    Pour du one-shot, l'indirection me semble quand même la solution la plus rapide à mettre en oeuvre et présente l'avantage de la compréhension immédiate dans 6 mois par le petit nouveau qui viendra prendre le relais...

Discussions similaires

  1. [MFC-QT]message map dynamique
    Par farscape dans le forum MFC
    Réponses: 4
    Dernier message: 03/03/2005, 16h33

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