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 :

Dll d'extension MFC et CDialog


Sujet :

MFC

  1. #1
    Membre confirmé
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Avril 2005
    Messages
    87
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Avril 2005
    Messages : 87
    Par défaut Dll d'extension MFC et CDialog
    Bonjour à tous.

    Je suis chargé d'isoler la couche de communication d'un logiciel dans une DLL. J'isole donc dans une DLL le bus et le protocole.
    En consultant les tutoriels, j'ai remarqué celui de Farscape : "DLL d'extensions : écriture d'un plug-in de classe". L'avantage de cette méthode est d'utiliser la classe de la DLL comme si elle faisait partie du projet (si j'ai bien tout compris, je suis novice en DLL...)
    J'ai donc mis cela en œuvre, ce qui marche très bien jusqu'au moment où j'ai voulu ajouter une boite de dialogue dans la DLL pour la configuration. Et là... Assert dans le code MFC lorsque je tente de faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    CMyDlg dlg;
    dlg.DoModal();
    Après une petite recherche, pour utiliser une boite de dialogue dans une DLL, il faut faire précéder son utilisation par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    AFX_MANAGE_STATE(AfxGetStaticModuleState());
    Mais là, le linker n'en veut pas : symboles déjà définis DllMain... (je n'ai plus les messages exacts en tête).
    Alors est-ce que je fait fausse route en utilisant ce type de DLL (extension MFC) ? Faut il que je repasse au type Shared MFC DLL ?
    J'avoue que je suis un peu perdu ; merci par avance de vos explications et conseils !

    edit : je ne pense pas que ça ait une grande influence, mais ce projet est sous VC++98

  2. #2
    Membre confirmé
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Avril 2005
    Messages
    87
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Avril 2005
    Messages : 87
    Par défaut
    Typiquement, mon problème est celui décrit dans cette TN : DOC: AfxGetStaticModuleState() Causes Errors in an Extension DLL ; mais ça ne me dit toujours pas comment ouvrir ma Dlg dans ma DLL...

  3. #3
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

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

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Par défaut
    salut,
    essaye:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    AFX_MANAGE_STATE(AfxGetAppModuleState());

  4. #4
    Membre confirmé
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Avril 2005
    Messages
    87
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Avril 2005
    Messages : 87
    Par défaut
    Salut Farscape,
    merci de ta réponse, ça ne passe pas non plus :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    AFX_MANAGE_STATE(AfxGetAppModuleState());
    CMyDlg dlg;
    dlg.DoModal();
    La dialogue que j'instancie localement semble valide dans le débugger, mais a un hWnd à 0.
    J'ai testé l'autre solution au cas où...:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    AFX_MANAGE_STATE(AfxGetAppModuleState());
    CMyDlg* pDlg = new CMyDlg();
    pDlg->DoModal();
    Pas mieux.
    On est bien d'accord que dans la théorie, il est possible d'ajouter des boites de dialogues depuis une DLL d'extension MFC ?

  5. #5
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

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

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Par défaut
    oui, en fait il faut switcher les ressources entre la dll et le programme avec AfxSetResourceHandle un peu comme dans ce post :
    http://cpp.developpez.com/faq/vc/?pa...gMultiLanguage
    il faut que tu fasses une fonction dans ta dll qui renvoie son handle de ressource avec AfxGetResourceHandle.
    et tu alternes de l'un a l'autre ..
    tu peux peux faire un objet qui lorsqu'il est initialisé change le contexte.
    et quand il se détruit remet celui du programme.

    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
     
    class SwitchResourceDll
    {
    public:
        SwitchResourceDll(HINSTANCE hInstDll)
        {
            m_hInst = AfxGetResourceHandle();// sauvegarde le contexte.
            AfxSetResourceHandle(hInstDll);
        }
     
        ~SwitchResourceDll()    // restauration du contexte.
        {
            AfxSetResourceHandle(m_hInst);
        }
     
    private:
        HINSTANCE m_hInst;
    };
    extern "C" HINSTANCE GetDllInstance();
     
    {
      SwitchResourceDll SwitchDll(GetDllInstance());
      CMyDlg dlg;
      dlg.DoModal();
    }

  6. #6
    Membre confirmé
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Avril 2005
    Messages
    87
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Avril 2005
    Messages : 87
    Par défaut
    Merci Farscape de tes réponses.
    Mais j'ai un peu de mal à comprendre ton exemple. Visiblement, l'instance de SwitchResourceDll est utilisée au sein de la DLL, à l'endroit précis où j'ai besoin d'effectuer le changement de resources. Mais dans ce cas, si le changement s'effectue depuis la DLL, pourquoi mettre la méthode GetDllInstance() externe ?
    Pour être honnête, je ne voie pas très bien pourquoi l'on ne fait pas simplement:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    HINSTANCE hExeInst = AfxGetResourceHandle(); // sauvegarde
    HINSTANCE hDllInst = AfxGetInstanceHandle();
    AfxSetResourceHandle(hDllInst); // mise à jour
     
    UartConfigDlg confDlg;
    confDlg.DoModal();
     
    AfxSetResourceHandle(hExeInst);// restauration
    Mis à part l'assert à l'exécution ?

  7. #7
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

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

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Par défaut
    bon j'ai fait l'exemple suivant:
    dans ma dll d'extension j'ai déclaré une dialogue.
    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
     
    static HINSTANCE hInstDll;
     
    extern "C" int APIENTRY
    DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
    {
        // Remove this if you use lpReserved
        UNREFERENCED_PARAMETER(lpReserved);
     
        hInstDll=hInstance;
        if (dwReason == DLL_PROCESS_ATTACH)
        {
            TRACE0("TESTDLL.DLL Initializing!\n");
     
            // Extension DLL one-time initialization
            if (!AfxInitExtensionModule(TestDllDLL, hInstance))
                return 0;
     
            // Insert this DLL into the resource chain
            // NOTE: If this Extension DLL is being implicitly linked to by
            //  an MFC Regular DLL (such as an ActiveX Control)
            //  instead of an MFC application, then you will want to
            //  remove this line from DllMain and put it in a separate
            //  function exported from this Extension DLL.  The Regular DLL
            //  that uses this Extension DLL should then explicitly call that
            //  function to initialize this Extension DLL.  Otherwise,
            //  the CDynLinkLibrary object will not be attached to the
            //  Regular DLL's resource chain, and serious problems will
            //  result.
     
            new CDynLinkLibrary(TestDllDLL);
        }
        else if (dwReason == DLL_PROCESS_DETACH)
        {
            TRACE0("TESTDLL.DLL Terminating!\n");
            // Terminate the library before destructors are called
            AfxTermExtensionModule(TestDllDLL);
        }
        return 1;   // ok
    }
    extern "C" AFX_EXT_API void AffDlg(HINSTANCE hInst)
    {
        HINSTANCE savhInst=hInst;
     
        AfxSetResourceHandle(hInstDll);
     
        MyDialog Dlg;
        Dlg.DoModal();
        AfxSetResourceHandle(savhInst);
    }
    et une fonction pour appeler cette dialogue de l'extérieur..
    cette fonction recoit l'instance de l'application principale
    fixe les ressources sur la dll
    appel la dialogue.
    restitue les ressources sur l'application principale
    coté applicatif:
    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
     
    void CTestmainDlg::OnButton() 
    {
        // TODO: Add your control notification handler code here
        HINSTANCE hDLL = LoadLibrary("c:/samples/Vol1/testDll/Debug/testdll.dll");
        if((unsigned int)hDLL<0x20)
        {
            TRACE(_T("\nDLL non trouvée ou Erreur consultez GetLastError() !!!"));
            return ;    
        }
     
        typedef void ( * LPDLLFUNC)(HINSTANCE);
        LPDLLFUNC lpfnDllFunc = NULL;
        lpfnDllFunc = (LPDLLFUNC)::GetProcAddress(hDLL,_T("AffDlg"));
        if (!lpfnDllFunc)
        {
            FreeLibrary(hDLL);
            return;
        }
        lpfnDllFunc(AfxGetResourceHandle());
     
        FreeLibrary(hDLL);
    }
    je lis ma dll,
    je récupère l'adresse de ma fonction et je passe l'instance de l'application.
    ça fonctionne très bien..
    quelque soit l'endroit ou est fait l'appel le principe reste le même : il faut switcher les ressources entre la dll et le programme principale...

  8. #8
    Membre confirmé
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Avril 2005
    Messages
    87
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Avril 2005
    Messages : 87
    Par défaut
    Merci Farscape pour tes réponses.

    Je viens de recréer un projet de démo (comme tu l'as fait) et effectivement, ça marche très bien. Par contre, appliqué dans le projet sur lequel je travaille, cela ne marche toujours pas, même si le changement de resource s'effectue bien (vérifié par des appels successifs à AfxGetResourceHandle).
    C'est encore sur le DoModal que claque l'assert.
    Je ne marque pas encore le topic comme résolu ; je cherche à corriger mon erreur d'abord.

    Cordialement,
    Aymerik

  9. #9
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

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

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Par défaut
    le probléme vient peut être de ta dialogue par exemple un probléme sur un contrôle.
    si tu utilises la dll en debug tu peux la debuger .
    Ensuite place des points d'arrêts dans DoDataExchange et OnInitDialog.
    et trace pas a pas.

  10. #10
    Membre confirmé
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Avril 2005
    Messages
    87
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Avril 2005
    Messages : 87
    Par défaut
    Je ne pense pas que cela vienne de la Dialog : je passe bien dans le constructeur, mais pas dans le OnInitDialog.
    J'ai fait le test avec une nouvelle dialog "vide", mais l'assert est le même.
    voici la call stack au moment de l'assert:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    AfxGetInstanceHandle() line 19 + 33 bytes
    AfxEndDeferRegisterClass(long 0x00000010) line 3633 + 5 bytes
    CWnd::CreateDlgIndirect(const DLGTEMPLATE * 0x0211d528, CWnd * 0x00000000 {CWnd hWnd=???}, HINSTANCE__ * 0x02100000) line 277 + 7 bytes
    CDialog::DoModal() line 528 + 32 bytes
    TestDlg(HINSTANCE__ * 0x00400000) line 58 // Méthode externe de ma DLL
    me renvoyant à ce code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    _AFXWIN_INLINE HINSTANCE AFXAPI AfxGetInstanceHandle()
    	{ ASSERT(afxCurrentInstanceHandle != NULL);
    		return afxCurrentInstanceHandle; }
    L'assert présenté claque : ce qui me fait plus penser au problème de ressource évoqué précédement qu'autre chose...

  11. #11
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

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

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Par défaut
    attention que le handle d'instance de l'application doit être demandé a partir du programme principal pas dans la DLL.
    ce qui correspond a cette ligne dans mon exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
     lpnDllFunc(AfxGetResourceHandle());
    celui de la dll peut être sauvegardé dans DllMain

  12. #12
    Membre confirmé
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Avril 2005
    Messages
    87
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Avril 2005
    Messages : 87
    Par défaut
    Mais je fais tout pareil que toi !

  13. #13
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

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

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Par défaut
    hé bien ça ne doit pas être tout a fait pareil
    fait afficher avec des traces (TRACE) la valeurs des handles d'instance (avec %X):
    - dans le programme principal :
    le handle de l'application.
    celui de la dll lue.

    - dans la dll au moment de la demande d'affichage de la dialogue:
    celui de l'application que tu dois avoir récupéré.
    celui de la DLL.

    compare les valeurs ,c'est pareil ?

  14. #14
    Membre confirmé
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Avril 2005
    Messages
    87
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Avril 2005
    Messages : 87
    Par défaut
    Bon d'accord, ça ne doit pas être tout à fait pareil !
    J'avance petit à petit :
    - j'ai pris ma classe décrivant ma dialog et je l'ai copiée dans mon projet de test : elle s'affiche correctement ; elle n'est donc pas en cause ;
    - j'ai tracé les adresses des instances comme tu me l'as suggéré, et elles correspondent entre l'application et la DLL (tout en étant non nulles bien sûr !)

    je continue à creuser...

    edit : je précise le "elles correspondent" :l'adresse de l'instance de l'application a la même valeur hVal1 depuis l'appli et depuis la DLL ; l'adresse de l'instance de la DLL a la même valeur hVal2 depuis l'appli et depuis la DLL.

  15. #15
    Membre confirmé
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Avril 2005
    Messages
    87
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Avril 2005
    Messages : 87
    Par défaut
    Je progresse mais arrive en face d'un mur ...
    Le problème ne vient pas de la DLL, mais de l'application. En effet, pour tester cela, j'ai compilé ma DLL depuis mon workspace de travail, et l'ai chargé depuis mon application de test (créée pour l'occasion). Cela fonctionne très bien.
    Je me suis rendu compte que le problème vient plus précisement des options de compilations. Mais là, je me perd
    - Mon appli utilise les MFC en statique, ainsi que des DLL MFC statiques.
    - j'essaie de charger des DLL MFC dynamiques

    Citation Envoyé par msdn
    Caution Do not mix static and dynamic versions of the run-time libraries. Having more than one copy of the run-time libraries in a process can cause problems, because static data in one copy is not shared with the other copy. The linker prevents you from linking with both static and dynamic versions within one .exe file, but you can still end up with two (or more) copies of the run-time libraries. For example, a dynamic-link library linked with the static (non-DLL) versions of the run-time libraries can cause problems when used with an .exe file that was linked with the dynamic (DLL) version of the run-time libraries. (You should also avoid mixing the debug and non-debug versions of the libraries in one process.)
    Donc j'ai fait fausse route avec ces DLL d'extension MFC

    Je repars vers des DLL statiques.
    En tous cas, merci beaucoup Farscape

  16. #16
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

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

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Par défaut
    salut,
    En effet les dll d'extensions imposent de travailler en dll MFC partagées...

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 12/08/2009, 17h17
  2. Réponses: 1
    Dernier message: 31/01/2008, 16h55
  3. DLL d'extension
    Par PRUVOT dans le forum MFC
    Réponses: 1
    Dernier message: 26/10/2005, 15h41
  4. [MFC] Variable global et DLL d'extension
    Par Capnader dans le forum MFC
    Réponses: 2
    Dernier message: 31/03/2005, 11h33
  5. Réponses: 9
    Dernier message: 03/12/2004, 11h35

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