Bonjour tout le monde, je suis nouveau z'ici. J'espère que des âmes charitables auront la grâce de se pencher sur mon épineux problème. Y'en a un peu long, désolé.
Je n'arrive pas à faire passer des informations à des composants activeX "maison". Voilà la situation actuelle (qui fonctionne).
Plusieurs composants activeX ont été créés, avec Visual Basic 6.0. Ils implémentent tous une même interface, qui comprend, entre autres, la fonction suivante :
m_ConnectData est un objet de type Connection. Le but de chaque activeX, en gros, c'est d'aller chercher des infos dans une base de donnée et de les afficher. En théorie, c'est peut-être pas à ça que doivent servir les activeX, mais le logiciel a été fait comme ça, tout chambouler serait un peu long et fastidieux.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 Public Sub InterfaceActiveX_SetNomDatabaseData(NomDatabase As String) m_NomDatabaseData = NomDatabase If m_ConnectData.State = adStateClosed Then m_ConnectData.ConnectionString = NomDatabase m_ConnectData.Open End If End Sub
Après j'ai le projet principal, codé en C++ avec Visual C++ 6.0. Ce projet s'occupe d'instancier les activeX et de leur passer les bonnes informations. J'ai donc une fonction de ce genre dans ce projet :
Dans cette situation, tout se passe bien. Le projet principal crée un ou plusieurs activeX, il donne la chaîne de connexion, et chaque activeX va gentiment se connecter dans son coin, pour récupèrer des données et les afficher. C'est très youpi.
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 void CInterfaceActiveX::SetNomDatabaseData(CString sNomDatabase) { OLECHAR FAR* szMember = L"InterfaceActiveX_SetNomDatabaseData"; static BYTE parms[] = VTS_BSTR; CString strChaineConnexion; /* ici il y a du code permettant de donner la bonne valeur à strChaineConnexion, quelque chose de ce genre : "DRIVER={SQL Server};SERVER=machin;database=bidule;UID=truc;PWD=tralala" */ InvokeHelper(__GetDispID(szMember), DISPATCH_METHOD, VT_EMPTY, NULL, parms, strChaineConnexion); }
Le problème c'est que les activeX sont créés, puis détruits puis recréés, assez souvent durant l'exécution du logiciel. Donc on se retrouve avec des connexions de bases de données qui s'ouvrent et se ferment à chaque fois. Et la pauvre base de données a du mal. Au début on avait un gentil fichier Access en local, ça ne le dérangeait pas d'avoir des dizaines de connexion qui durent très peu de temps chacune. Mais là on va passer à une grosse base SQL sur un serveur, donc il faudrait essayer de se limiter. Une exécution du logiciel = une seule connexion.
L'idéal serait que le projet principal se connecte à la base de données (en fait il le fait déjà, car il a lui aussi besoin d'y récupérer des infos) et qu'ensuite cette connexion soit donnée aux différents activeX. La tâche d'établir la connexion doit être transférée au module de niveau supérieur. Donc mon code devrait ressembler à ça :
dans les activeX :
et dans mon projet principal :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 Public Sub InterfaceActiveX_SetConnectionData(ConnectData As Connection) m_ConnectData = ConnectData End Sub
theApp.m_DatabaseData est un objet de type CDaoDatabase. Au moment où la fonction SetNomDatabaseData est exécutée, la connexion de m_DatabaseData est déjà ouverte. Il y a d'autres parties du code qui l'utilisent avant, et ça marche très bien.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10 void CInterfaceActiveX::SetNomDatabaseData(CString sNomDatabase) { OLECHAR FAR* szMember = L"InterfaceActiveX_SetConnectionData"; static BYTE parms[] = VTS_CONNECTION; //sauf que ce nom n'existe pas. InvokeHelper(__GetDispID(szMember), DISPATCH_METHOD, VT_EMPTY, NULL, parms, theApp.m_DatabaseData); }
D'après ce que j'ai compris, la variable parms sert à spécifier les types de paramètres que l'on passe à la fonction exécutée par l'activeX. Dans la situation précédente, je devais passer la string de connection, donc il fallait indiquer : VTS_BSTR. On peut utiliser d'autres types assez simple, du genre VTS_I4 ou VTS_I2 pour des entiers, VTS_BOOL pour des booléens, etc... Mais je n'ai pas trouvé de nom du style VTS_CONNECTION ou VTS_DAO_CONNECTION.
J'ai essayé avec VTS_VARIANT
J'ai un message d'erreur à l'exécution, au moment où le logiciel essaie de transmettre la connexion :
"Types non correspondant"
avec VTS_UNKNOWN
message d'erreur : "L'instruction à "0x51ec8b55" emploie l'adresse mémoire "0x51ec8b55". La mémoire ne peut pas être "read". Appuyez sur OK pour fermer, sur Annuler pour déboguer."
avec VTS_PVARIANT, et en mettant comme paramètre &(theApp.m_DatabaseData) au lieu de theApp.m_DatabaseData
message d'erreur : "Types non correspondant"
Et j'ai essayé aussi en changeant la fonction InterfaceActiveX_SetConnectionData. Au lieu de déclarer le paramètre ConnectData comme une Connection, je la déclare comme un Variant.
Dans ce cas, avec VTS_VARIANT et VTS_PVARIANT, j'ai ce message d'erreur :
"La variable utilise un type Automation non géré par Visual Basic"
avec VTS_UNKNOWN
message d'erreur : "L'instruction à "0xb8fc4d89" emploie l'adresse mémoire "0xb8fc4d89". La mémoire ne peut pas être "read". Appuyez sur OK pour fermer, sur Annuler pour déboguer."
Voili voilà. Ma question est donc : puis-je transmettre à un activeX un objet représentant une connexion Dao ouverte ? Si oui comment ?
Merci d'avance pour vos réponses.
Partager