Programmation de librairies dll win32
pour Access avec Visual C++ Express
Date de publication : 24/11/06 , Date de mise à jour : 24/11/06
I. Introduction
I-A. Liens
I-B. Pourquoi Visual C++ Express?
I-C. Remerciements
II. Installation
II-A. Installation de Visual C++ Express
II-B. Installation du Platform SDK
II-C. Paramétrage de l'environnement de développement (IDE)
III. Créer un nouveau projet
IV. Configurer le projet
V. Créer une première librairie contenant une procédure simple
V-A. Fichier d'en-tête Windows
V-B. Ajouter une procédure à la librairie
V-C. Générer la librairie
V-D. Exécuter la procédure à partir d'Access
V-E. Passer des paramètres à la procédure
V-D-1. Variables
V-D-2. Tableaux
V-F. Transformer la procédure en fonction
V-G. Conclusion
I. Introduction
I-A. Liens
I-B. Pourquoi Visual C++ Express?
Il est d'abord souvent nécessaire de déporter les sous-classements (=Hook) dans une librairie
pour assurer la stabilité de l'application.
Ensuite l'environnement de développement Visual Express est gratuit (pour une utilisation personnelle ou professionnelle).
Et enfin C++ parce que ce langage permet de créer des librairies simples (VB ne permet de créer que des librairies ActiveX qui nécéssite un référencement).
I-C. Remerciements
Merci à la
rédaction Access de DVP pour le temps passé en relectures et tests.
Merci à tous ceux qui partagent leurs connaissances sur internet et sans qui je n'aurais pas pu réaliser cet article.
II. Installation
Pour programmer une librairie win32 en Visual C++, il faut au préalable installer :
- L'environnement de développement Visual C++ Express
- Le Platform SDK pour disposer des fichiers d'en-tête win32
- Le Framework est installé obligatoirement avec Visual C++, même si nous ne l'utiliserons pas
|
Il n'est pas nécessaire de graver les images ISO.
Vous pouvez utilisez Daemon tools pour créer un disque virtuel à partir de l'image ISO.
|
II-A. Installation de Visual C++ Express
II-B. Installation du Platform SDK
II-C. Paramétrage de l'environnement de développement (IDE)
1 - Ajoutez les répertoires du Platform SDK :
- Ouvrez Visual C++ Express
- Dans le menu :
Outils -->
Options..., choisissez
Projets et solutions et sélectionnez
Répertoires de VC++
a - Ajoutez :
C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Bin dans
Fichiers exécutables comme ceci :
b - Puis ajoutez
C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Include dans
Fichiers Include
c - Et
C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\lib dans
Fichiers bibliothèques
(Ces répertoires sont les répertoires par défaut si vous n'avez rien changé lors de l'installation).
2 - Modifier les dépendances :
Dans le fichier
C:\Program Files\Microsoft Visual Studio 8\VC\VCProjectDefaults\corewin_express.vsprops,
remplacez
AdditionalDependencies="kernel32.lib"
|
par
AdditionalDependencies="kernel32.lib user32.lib gdi32.lib winspool.lib
comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib"
|
Mettez tout le texte sur la même ligne.
(vous pouvez éditer le fichier avec Notepad ou WordPad par exemple)
3 - Activer l'assistant pour créer une application ou une librairie Win32
Dans le fichier C:\ProgramFiles\Microsoft Visual Studio 8\VC\VCWizards\AppWiz\Generic\Application\html\1036\AppSettings.htm,
remplacez à l'aide d'un éditeur de texte (Notepad ou WordPad par exemple) :
WIN_APP.disabled = true;
WIN_APP_LABEL.disabled = true;
DLL_APP.disabled = true;
DLL_APP_LABEL.disabled = true;
|
par:
// WIN_APP.disabled = true;
// WIN_APP_LABEL.disabled = true;
// DLL_APP.disabled = true;
// DLL_APP_LABEL.disabled = true;
|
Ceci se trouve en ligne 441 à 444.
Vérifiez que vous modifiez bien au bon endroit, là où se trouvent ces 4 lignes en un seul bloc.
Notez que le 1036 en fin de chemin du fichier peut différer en fonction de la langue d'installation.
III. Créer un nouveau projet
Tous les fichiers sources sont regroupés dans un projet.
Pour créer un nouveau projet, choisissez dans le menu :
Fichier -->
Nouveau -->
Projet
Dans le fenêtre qui apparaît, donnez un nom au projet.
Le nom de la librairie sera celui du projet.
Par exemple j'ai choisi
TestCPP comme nom de projet, la librairie sera générée sous le nom
TestCPP.dll.
L'assistant se déclenche, cliquez sur
Suivant.
Sélectionnez ensuite
DLL pour générer un projet de librairie.
Puis cliquez sur
Terminer.
L'assistant crée les fichiers nécessaires à la création d'une librairie :
-
stdafx.h : fichier d'entête contenant les déclarations.
-
stdafx.cpp : fichier source qui inclue le précédent fichier d'en-tête.
-
TestCPP.cpp : c'est le fichier source principal dans lequel on va ajouter notre code.
IV. Configurer le projet
Il y a deux configurations par défaut pour un nouveau projet :
-
Debug
-
Release
La configuration
Debug possède par défaut des paramètres utiles au débogage.
La librairie étant utilisée à partir de Access, on ne va pas la déboguer.
On choisi donc la configuration Release dans le menu déroulant (en haut dans la barre de menu).
C'est sur cette configuration que l'on va définir les paramètres de notre projet.
Sélectionnez le projet
TestCPP dans le panneau de gauche :
Choisissez dans le menu :
Projet -->
Propriétés
Dans les
Propriétés de configuration :
Général, vérifiez les paramètres suivants :
- Type de configuration : Bibilothèque dynamique (dll)
- Utilisation des MFC : Utiliser les bibliothèques Windows standard
- Utilisation des ATL : N'utilisant pas ATL
- Reduction de l'utilisation des CRT dans les ATL : Non
- Jeu de caractères : Utiliser le jeu de caractères multioctet (MBCS)
(ce dernier paramètre simplifie l'utilisation des chaînes de caractères)
Dans les
Propriétés de configuration :
C/C++ :
Général :
- Détection des problèmes de portabilité 64bits : Non
(Pour une librairie Win32, inutile d'afficher les avertissements liés au 64Bits)
Dans les
Propriétés de configuration :
C/C++ :
Génération de code :
- Bibliothèque runtime : Multithread (/MT)
(important pour ne pas avoir à installer de runtime sur les PC)
V. Créer une première librairie contenant une procédure simple
On va, pour débuter en douceur, simplement afficher un message à l'aide de l'équivalent de MsgBox en C++.
V-A. Fichier d'en-tête Windows
On ajoute tout de suite la déclaration du fichier d'en-tête Windows dans le fichier stdafx.h.
(Ajoutez ce code en fin du fichier.)
Ce fichier contient les déclarations des fonctions et constantes communément utilisées, notamment pour notre exemple MessageBox et MB_OK.
V-B. Ajouter une procédure à la librairie
Pour exécuter un traitement sans recevoir de résultat, une procédure est suffisante.
A la fin du fichier TestCPP.cpp ajouter la procédure suivante :
void __stdcall TestMessage ()
{
MessageBox (NULL ," test message " ," test titre " ,MB_OK);
}
|
- void signifie que la procédure ne renvoie pas de résultat.
- _stdcall est nécessaire pour pouvoir exécuter la fonction depuis VBA.
- TestMessage est le nom de la procédure.
- MessageBox est la fonction C++ qui permet d'afficher un message.
Retrouvez l'aide de la fonction dans la documentation du PlatForm SDK
Pour que la procédure soit exportée, et donc exécutable à partir de VBA, il faut écrire un fichier de définition de module.
- Dans le menu : Fichier --> Nouveau --> Fichier...
- Choisissez dans Général : Fichier texte
- Sauvegardez ce fichier sous le nom TestCPP.def.
Ce fichier contient les noms des fonctions à exporter :
LIBRARY TestCPP
EXPORTS
TestMessage @1
|
Les fonctions/procédure sont numérotées dans l'ordre d'apparition dans le code.
Cela signifie qu'on exporte la première procédure (
@1) sous le nom
TestMessage.
Il faut ensuite demander au compilateur d'utiliser ce fichier de définition.
Dans les propriétés du projet :
Propriétés de configuration :
Editeur de liens :
Entrée.
Fichier de définition de module : TestCPP.def
V-C. Générer la librairie
Dans le menu, choisissez : Générer --> Générer TestCPP.
Voci le protocole de génération :
- - - - - - Début de la génération : Projet : TestCPP, Configuration : Release Win32 - - - - - -
Compilation en cours...
stdafx.cpp
Compilation en cours...
TestCPP.cpp
Édition des liens en cours...
Création de la bibliothèque E:\Transfert_doc\Programmation\VCExpress\TestCPP\Release\TestCPP.lib
et de l' objet E:\Transfert_doc\Programmation\VCExpress\TestCPP\Release\TestCPP.exp
Génération de code en cours
Fin de la génération du code
Incorporation du manifeste en cours...
Le journal de génération a été enregistré à l' emplacement
" file://e:\Transfert_doc\Programmation\VCExpress\TestCPP\TestCPP\Release\BuildLog.htm "
TestCPP - 0 erreur (s), 0 avertissement (s)
= = = = = = = = = = Génération : 1 a réussi, 0 a échoué, 0 mis à jour, 0 a été ignoré = = = = = = = = = =
|
La librairie a été générée dans le répertoire :
E:\Transfert_doc\Programmation\VCExpress\TestCPP\Release\
Le nom du fichier est :
TestCPP.dll
On peut maintenant utiliser cette librairie à partir d'Access.
V-D. Exécuter la procédure à partir d'Access
La procédure TestMessage étant dans un fichier séparé, il faut tout d'abord la déclarer.
Dans un module VBA, ajouter la déclaration suivante :
Public Declare Sub TestMessage Lib " E:\Transfert_doc\Programmation\VCExpress\TestCPP\release\TestCPP.dll " ()
|
N'oubliez pas de modifier le répertoire pour indiquez celui où se trouve votre librairie.
Si vous mettez les déclarations de fonctions externes (mot-clé Declare) dans un module de classe (ceci inclue les modules de formulaires),
il faut déclarer les fonctions en Private au lieu de Public.
Ensuite vous pouvez exécuter la procédure, par exemple sur click sur un bouton de formulaire :
Private Sub CmbTestDll_Click ()
TestMessage
End Sub
|
Il est heureusement possible de définir dynamiquement le chemin de la librairie.
Pour cela, ne précisez pas le chemin dans la déclaration de la procédure.
La librairie sera chargée grâce à la fonction LoadLibrary (c'est une API à déclarer).
Nouvelles déclarations |
Public Declare Sub TestMessage Lib " TestCPP.dll " ()
Public Declare Function LoadLibrary Lib " Kernel32 " Alias " LoadLibraryA " (ByVal lpLibFileName As String ) As Long
|
Appel de la fonction avec chargement de la dll dans le répertoire de l'application Access |
Private Sub CmbTestDll_Click ()
LoadLibrary Left (CurrentDb. Name , Len (CurrentDb. Name ) - Len (Dir (CurrentDb. Name ))) & " TestCPP.dll "
TestMessage
End Sub
|
V-E. Passer des paramètres à la procédure
V-D-1. Variables
Pour personnaliser la boîte de message on va passer en paramètre :
- le texte du message;
- le titre de la boîte de dialogue.
On s'aperçoit également que la boîte de dialogue ne reste pas en avant plan:
il faut utiliser le premier paramètre de la fonction MessageBox pour préciser l'identifiant de la fenêtre parent
On ajoute donc trois paramètres :
- pHwnd : un entier long qui contiendra l'identifiant de l'application Access ou du formulaire;
- pTexte : une chaîne de caractères qui contient le texte du message;
- pTitre : une chaîne de caractères qui contient le titre de la boîte de dialogue.
Pour un entier long, on utilise le type C++ DWORD.
Pour une chaîne de caractères, on utilise le type C++ BSTR.
Le type BSTR est défini dans le fichier d'entête "olectl.h".
On ajoute d'abord ce fichier d'entête dans le fichier stdafx.h, à la fin du fichier dans la partie "// Fichiers d'en-tête Windows :":
# include <windows.h>
# include "olectl.h"
|
Ensuite on modifie la déclaration de la procédure :
void __stdcall TestMessage (DWORD pHwnd,BSTR pTexte,BSTR pTitre)
|
Puis on utilise ces paramètres dans la fonction MessageBox:
void __stdcall TestMessage (DWORD pHwnd,BSTR pTexte,BSTR pTitre)
{
MessageBox (HWND (pHwnd),LPCSTR (pTexte),LPCSTR (pTitre),MB_OK);
}
|
Le premier paramètre de la fonction MessageBox est de type HWND.
On converti donc notre paramètre de type DWORD en ajoutant HWND lors de son utilisation.
Les paramètres suivant sont de type LPCSTR, on les converti de la même manière
N'oubliez pas de régénérer la librairie après ces modifications.
Il peut être nécessaire de fermer l'application Access pour pouvoir générer la librairie.
Les paramètres ajoutés doivent être préciser dans la déclaration VBA de la fonction dans Access.
Notez l'importance du mot-clé ByVal qui précise que les paramètres sont passés par valeur.
Public Declare Sub TestMessage Lib " E:\Transfert_doc\Programmation\VCExpress\TestCPP\release\TestCPP.dll " _
(ByVal pHwnd As Long, ByVal pTexte As String , ByVal pTitre As String )
|
L'appel de la fonction dans le formulaire devient :
Private Sub CmbTestDll_Click ()
TestMessage Me. Hwnd , " Mon message " , " Mon Titre "
End Sub
|
Me.Hwnd est l'identifiant du formulaire. Cela permet de lier la boîte de message au formulaire.
Si la fonction est utilisée dans un module standard, on peut utiliser
Application.hWndAccessApp pour lier la boîte de
dialogue à l'application Access.
On obtient une boîte de dialogue toute simple:
On a tout de même réussi à passer des paramètres à notre librairie!
V-D-2. Tableaux
V-F. Transformer la procédure en fonction
La procédure ne renvoie pas de résultat.
On ne connaît donc pas le choix de l'utilisateur.
La prochaine étape consiste à transformer la procédure en fonction pour appeler une
boîte de message de type OUI/NON et récupérer dans Access la choix de l'utilisateur.
Pour transformer la procédure en fonction, il suffit de remplacer Void par le type de donnée à retourner.
D'après la documentation, la fonction MessageBox retourne un résultat de type entier int.
int __stdcall TestMessage (DWORD pHwnd,BSTR pTexte,BSTR pTitre)
{
int lResultat;
lResultat = MessageBox (HWND (pHwnd),LPCSTR (pTexte),LPCSTR (pTitre),MB_YESNO);
Return lResultat;
}
|
On utilise une variable locale lResultat de type int pour récupérer la résultat de la boîte de dialogue.
L'instruction Return permet de quitter la fonction en renvoyant le contenu de la variable spécifiée.
Dans Access, la définition de la procédure doit être modifiée :
- ce n'est plus une procédure donc on remplace Sub par Function;
- et on ajoute le type de donnée à retourner par la fonction : int en C++ donc long en VBA.
Public Declare Function TestMessage Lib " E:\Transfert_doc\Programmation\VCExpress\TestCPP\release\TestCPP.dll " _
(ByVal pHwnd As Long, ByVal pTexte As String , ByVal pTitre As String ) As Long
|
Le résultat de MessageBox dans C++ est un entier dont la valeur peut-être IDYES ou IDNO.
Ces constantes ne sont pas définies dans VBA, il faut donc les déclarer.
Pour trouver les valeurs correspondantes à ces constantes C++, tapez IDYES dans l'éditeur C++
puis dans le menu contextuel (click sur bouton droit sur le mot IDYES) sélectionnez Atteindre la déclaration.
On trouve les valeurs des constantes :
# define IDYES 6
# define IDNO 7
|
Il suffit alors de déclarer l'équivalent dans VBA :
Public Const IDYES = 6
Public Const IDNO = 7
|
On peut ensuite comparer le résultat de la fonction TestMessage avec ces constantes.
Private Sub CmbTestDll_Click ()
Dim lResultat As Long
lResultat = TestMessage (Me. Hwnd , " Mon message " , " Mon Titre " )
MsgBox " Vous avez cliquez sur " & IIf (lResultat = IDYES, " Oui " , " Non " )
End Sub
|
Remarquez qu'on peut également directement utiliser les constantes VBA vbYes et vbNo.
V-G. Conclusion
Cette première procédure nous a permis de voir les bases de la programmation de librairie pour Access en C++.
Elle n'a pas d'autre intérêt, la fonction MsgBox de VBA suffirait à faire la même chose.
Les sources présentées sur cette page sont libres de droits
et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation
constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ©
Thierry GASPERMENT. Aucune reproduction, même partielle, ne peut être
faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc.
sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à
trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.