Les appels dAPIs en VB6 Quand on commence àfaire de la programmation proche du système, donc avancée,on a souvent besoin dAPI : fonctions proposées par lesystème dexploitation. Ces fonctions sont stockéesdans de bibliothèque de liens : les DLLs.
Il en existe troiscatégories principales :
User32.dll : toutes le fonctions en rapport avec les fenêtres
Gdi32.dll : tout ce qui est en rapport avec les images
Kernel32.dll : tout ce qui a rapport avec les mécanismes internes : informations système, système de fichier, mutes, sémaphores.
Déclaration
Les déclarationsdAPIs se font comme suit :
{Private|Public}Declare {Function|Sub} nom_fonction [Aliasvrai_nom_fonction] Lib nom_dll.dll(Param1 As Type1, Param2 As Type2,
ParamN As TypeN) [As TypeRetour]
{Private|Public} :portée de la déclaration (privée oupublique)
{Function|Sub} :fonction ou procédure, une API Windows est rarement uneprocédure (sauf CopyMemory)
[Aliasvrai_nom_fonction] : permet de renommer la fonction sisont vrai nom est, par exemple, trop long ou trop compliqué (_fct@8) ou pour importer des fonctions exportées par Index (dans cecas lalias sera #index).
Exemple :
PrivateDeclare Sub CopyMemory Lib "kernel32.dll" Alias"RtlMoveMemory" (ByRef Destination As Any, ByRef Source AsAny, ByVal Length As Long)
PrivateDeclare Function GetComputerName Lib "kernel32.dll" Alias"GetComputerNameA" (ByVal lpBuffer As String, ByRef nSizeAs Long) As Long
Pour trouver une déclarationdAPI, vous pouvez utiliser lAPI viewer ou tout autre liste surInternet.
Les paramètres
Il existe deux typesde paramètres : les paramètres par valeur et lesparamètres par référence (pointeur).
Un paramètrepar référence indique que lon passe ladresse dela variable à la fonction pour pouvoir modifier la variable àlintérieur. Le nom dun tel paramètre est précédéde ByRef ou rien (ByRef par défaut).
Un paramètrepar valeur indique que lon passe le contenu de la variable àla fonction. On ne peut donc pas modifier la variable àlintérieur de la fonction. Le nom dun tel paramètreest précédé de ByVal.
Deux types ne peuvent pas être ByVal :les tableaux et les structures.
Le type de retour
Si cest une Sub,alors il ny a pas de type de retour.
Sinon, cest presquetoujours un Long. Tout type de retour de plus de 4 octets devraitêtre passé par référence en paramètre.
Et si ma fonction nest pas dans une liste
Alors la cest unpeut plus compliqué. Mais si vous êtes là, cestque vous avez le prototype C de votre fonction.
Pour que VB puisse utiliser unefonction C comme une API, il faut :
Voici un tableau detypes courants et de leurs traductions VB6 :
| Type en C | Type en VB |
| char/BYTE | ByVal Byte (mais considéré non signé) |
| short | ByVal Integer |
| int | ByVal Long |
| long | ByVal Long |
| unsigned char | ByVal Byte |
| unsigned short/WORD/USHORT | ByVal Integer (mais considéré signé) |
| unsigned int/DWORD | ByVal Long (mais considéré signé) |
| unsigned long/ULONG | ByVal Long (mais considéré signé) |
| BOOL | ByVal Long (mais <> Boolean) |
| float | ByVal Single |
| double | ByVal Double |
| ULONGLONG, LONGLONG | ByVal Currency (considéré comme un flottant avec 4 décimales) |
| char* | ByVal String |
| short* | ByRef Integer |
| int* | ByRef Long |
| long* | ByRef Long |
| unsigned char* | ByRef Byte |
| unsigned short* | ByRef Integer (mais considéré signé) |
| unsigned int* | ByRef Long (mais considéré signé) |
| unsigned long* | ByRef Long (mais considéré signé) |
| BOOL* | ByRef Long (mais <> Boolean) |
| float* | ByRef Single |
| double* | ByRef Double |
| ULONGLONG*, LONGLONG* | ByRef Currency (considéré comme un flottant avec 4 décimales) |
| BSTR, LPWSTR* | ByVal Long et StrPtr pour le passage du parameter ou IDL (voir autre tuto) |
| BSTR* | ByVal Long et VarPtr pour le passage du parameter ou IDL (voir autre tuto) |
| Interface* | ByVal {Object|Interface} |
| Interface** | ByRef {Object|Interface} |
Structure | Voir plus bas |
| Structure* | ByRef Structure |
| SAFEARRAY(Type)* | ByRef Type() |
Tableau C | Voir plus bas |
Hxxx | Long (représente un handle) |
Les types pointeurs
Tous les typespointeurs peuvent être remplacés par ByVal Long. Dans cecas, on utilisera VarPtr(la_variable) ou StrPtr(la_variable)pour passer ladresse de la variable. Voir Travailler avec lespointeurs.
Les types Structures
Les types structuresne peuvent pas être passé par valeur. Pour pouvoir lespasser tout de même par valeur, il mettre autant de paramètresdans le Declare que de membre dans la structure.
Note sur lesstructures :
Parexemple :
PrivateType
BAs Byte
L As Long
EndType
Cettestructure prendra 8 octets de mémoire avec 3 octets de videentre B et L.
Ilfaut donc faire attention à lalignement dans les structuresC qui peut aller jusquà loctet (voir #pragma pack).
Les chaînes de taille fixe dans les structures (char nom[taille]) se traduisent en nom As String * taille
Les chaines char*, WCHAR* sont remplacées par Long. On utilise ensuite CopyMemory pour copier le contenu de la variable au bout du pointeur.
Les pointeurs sont interdits dans les structures VB6. On les remplace par Long et on utilise CopyMemory pour copier le contenu dans une autre variable. (CopyMemory ByVal pointeur,ByRef variable, taille_zone_pointée). Voir Travailler avec les pointeurs.
Les tableaux de taille fixe type nom[taille] se traduisent par nom(taille) As Type
Les unions nexistent pas : on les remplace par le membre de lunion qui a la plus grande taille en octets. Pour accéder à la donnée dune union dans un des autres types, on utilisera CopyMemory ByRef var_autre_type,ByRef membre_union, LenB(var_autre_type)
Pour les autres types :
| Type C | Type VB |
| char/BYTE | Byte (interprété non signé) |
| short/USHORT/WORD | Integer |
| int, long/DWORD/ULONG | Long |
| ULONGLONG | Currency |
| Float | Single |
| double | Double |
| BOOL/BOOLEAN | Long |
| bool | Byte |
Les types Tableaux
Les types tableaux nepeuvent pas être passé par valeur. On peut mais cesttrès difficile et très inutile.
Les tableaux VB6 nesont pas simplement une zone mémoire de donnée et unpointeur dessus. Toute une structure les accompagne.
Passer un tableau type C
Pour passer un tableaude type C, on a deux solutions :
ByRef Type_des_cases_du_tableau : dans ce cas, on passe la première case du tableau, en général, il y a un paramètre pour donner la taille du tableau que lon passe
Parexemple :
Dimt(10) As Long
Res= Fct(t(0),10)
Parexemple :
Dimt(10) As Long
Res= Fct(VarPtr(t(0)),10)
La seconde solutionpermet par exemple de passer plusieurs type de données àune fonction.
Passer un tampon chaîne ASCIItype C
Pour passer un bufferchaîne C : char* buffer (int taille, suit en général),on utilise un ByVal String. Il faut impérativement remplirla chaîne avec des caractères avant de la passer àla fonction.
Parexemple :
Dim sas string
s =space(20)
res =Fct(s,20)
Passer un tampon chaîneUNICODE type C
Pour passer un bufferchaîne C : wchar* buffer (int taille, suit en général),on utilise un ByVal Long. Il faut impérativement remplir lachaîne avec des caractères avant de la passer àla fonction. Comme les chaîne VB6 sont UNICODE, on passeStrPtr(le_buffer) à la fonction.
Parexemple :
Dim sas string
s =space(20)
res =Fct(StrPtr(s),20)
Any
Ce type spécialpermet de passer nimporte quel type au paramètre de lafonction. On peut utiliser les mots ByVal et ByRef dans les appels defonctions.
Passer un pointeur de fonction
Pour passer unpointeur de fonction, on utilise un ByVal Long et AddressOf danslappel de fonction. Cette fonction doit être dans unmodule (bas).
Par exemple :
res = Fct(AddressOfMaFonction)
Travailler avec les pointeurs
Tous les typespointeurs que vous avez remplacé par Long dans les structuresou les pointeurs de pointeurs (autres que Object) ne peuvent pas êtreutilisé directement par VB6. Pour accéder à ladonnée pointée il faut utiliser CopyMemory. La méthodeest la suivante :
Vous avez une adressedans un Long : membre de structure ou variable
Vous déclarezune variable du type de la donnée pointée :structure, type simple ou chaîne
Si la donnéepointée est une STRUCTURE ou type simple (Long, Integer,
) :
Dim variableAs Type
le pointeurest pointeur As Long
CopyMemoryByRef variable, ByVal pointeur, LenB(variable)
ou
CopyMemoryByVal VarPtr(variable), ByVal pointeur, LenB(variable)
Si la donnéepointée est un tableau C de STRUCTUREs ou types simples (Long,Integer,
) :
Dim variable()As Type
le pointeurest pointeur As Long et taille est le nombre de casesdu tableau
ReDimvariable(taille)
CopyMemoryByRef variable(0), ByVal pointeur, LenB(variable)* taille
ou
CopyMemoryByVal VarPtr(variable(0)), ByVal pointeur,LenB(variable) * taille
Si la donnéepointée est une chaîne ANSI :
lstrlenA :api renvoyant la taille ANSI dune chaîne de caractère
Private Declare Function lstrlenA Lib "kernel32.dll" (ByVallpString As Long) As Long
Dimvariable As String
lepointeur est pointeur As Long
taille =lstrlenA(pointeur)
variable =Space(taille)
CopyMemoryByVal StrPtr(variable), ByVal pointeur, taille +1
variable= StrConv(variable,vbUnicode)
Si la donnéepointée est une chaîne UNICODE :
lstrlenW :api renvoyant la taille UNICODE dune chaîne de caractère
Private Declare Function lstrlenW Lib "kernel32.dll" (ByVallpString As Long) As Long
Dimvariable As String
lepointeur est pointeur As Long
taille =lstrlenW(pointeur)
variable =Space(taille)
CopyMemoryByVal StrPtr(variable), ByVal pointeur, taille +2