Les API sont des appels à des routines qui sont contenues dans les .DLL.
J'ai testé : Apparemment, en aucun cas la syntaxe d'appel API n'est case-sensitive
Advapi32.DLL | Appels de sécurité, appels de service et registre |
comdlg32.dll | Boîtes de dialogues communes (Ouvrir, enregistrer, ...) |
Gdi32.DLL | Fonctions graphiques |
Kernel32.DLL | Noyau Windows (Mémoire, disque, CPU, ...) |
LZ32.dll | Compression 32 bits |
Mpr.DLL | Routeurs à fournisseurs multiples |
netapi32.dll | Réseaux 32 bits |
shell32.dll | API shell 32 bits |
user32.dll | Interfaces utilisateurs (fenêtres, menus, ...) |
version.dll | Gestion des différentes versions |
Winmm.DLL | Multimedia (son, midi, ...) |
winlnet.dll | Serveurs internet |
Il est nécessaire d'observer 2 points, parfois trois :
1. Déclaration de la fonction dans une section de déclaration d'un module
Il est possible de déclarer une sous-procédure ou une sous fonction
Syntaxe de la déclaration de la sous procédure :
Public ou Private Declare Sub NomProcédure Lib"NomDeLaProcédure" Alias "Pseudonyme" (ListeParametres)
Syntaxe de la déclaration de la sous-fonction :
Public ou Private Declare Sub NomFonction Lib"NomDeLaFonction" Alias "Pseudonyme" (ListeParametres) As Type
2. Création d'une routine/enveloppe appelant la routine DLL
3. Appeler la routine DLL
ATTENTION : Les DLLS sont Case-Sensitives
Cet exemple permet simplement de récupérer le nom du dossier de Windows.
Pour commencer, il faut préparer le terrain, et inscrire la définition de l'appel à l'API dans une section de déclaration d'un module :
Declare Function DossierWindows Lib "kernel32" Alias "GetWindowsDirectoryA" (ByVal lpBuffer As String, ByVal nSize As Long) As Long
DossierWindows | Nom d'alias : C'est un nom plus sympa que |
Lib "kernel32" | Nom de la DLL. Attention : S'il y a le chiffre 32, cette librairie ne pourra pas s'exécuter sous Windows 3.1/3.11 |
Alias "GetWindowsDirectoryA" | C'est le nom de la fonction telle qu'elle
apparaît dans la DLL. Dans le cas ou on ne définit pas d'Alias, ce serait ce nom de
fonction que l'on pourrait utiliser (Je n'ai pas testé de ne pas prendre d'alias). Le A
à la fin signifie que la routine est "en version ANSI (je ne comprend pas vraiment). Ce nom de fonction n'est pas case-sensitive |
ByVal | On passe ce premier argument par valeur. Ce qui est étrange dans le sens ou l'API va remplir cette chaîne (à cette adresse donc) avec le nom du dossier Windows |
lpBuffer As String | Il faudra lui passer une chaine de caractères de longueur 255. Pourquoi 255 ? Parce que c'est la longueur maximale du chemin d'accès Windows. C'est d'ailleurs toujours la longueur d'une chaîne de caractère renvoyée de cette façon, j'imagine. lpBuffer peut être remplacé par n'importe quel autre nom de variable |
ByVal nSize As Long | Contiendra la longueur effective de la
chaîne. Cette longueur sera donc stockée dans la variable de type Long dont on donnera
l'adresse en pâture comme 2ème paramètre (Si le dossier est C:\Windows, la variable
donnée en pâture à nSize contientra 10). nSize n'est pas case sensitive, et de toute façon, elle peut être remplacée par n'importe quel autre nom de variable |
As Long | Retour de la fonction. En l'occurrence, c'est la longueur effective du nom du chemin d'accès au dossier Windows, en l'occurrence 10 (et non pas 1 si la fonction s'est bien déroulée, comme on aurait pu s'y attendre) |
Ce qui est surtout intéressamnt de constater, c'est que les paramètres passés à l'API seront réellement remplis par la fonction elle même. Quand on crée une fonction personnelle, sans API, on est pourtant habitué à donner des paramètres qui ne changent pas au cours de la fonction, mais dans le cas des API, le principe est différent.
Par exemple, si on crée une fonction RacineCarree(ByVal Parametre), Parametre est tranquille. D'autant plus tranquille qu'on en passe une copie par valeur Mais dans notre exemple API, les variables qu'on donne comme lpBuffer sera, elle, bien remplacée par des données (par contre le 2ème paramètre nSize ne changera pas)
' On déclare la chaîne de caractère qui va ensuite contenir "C:\WINDOWS"
Dim ChainePointeurReceptrice As String
' On déclare une variable Long, qui, elle, va contenir la longueur effective de C:\WINDOWS (10)
Dim LongueurEffective As Long
' On prépare la chaîne (ici, on met 20 X, mais en fait, pour être propre, on devrait mettre 255 CHR$(0)) Pourquoi ? parce que les API ne sont pas aussi souples que VBA Access, et la réservation de place pour la chaîne n'est en fait que de 0 caractères si on n'assigne pas effectivement 20 places comme ici, ce qui fait que la chaîne n'aurait pas la place pour recevoir C:\WINDOWS. C'est seulement dans l'environnement de programmation VB ou VBA qu'on peut se permettre d'agrandir ou de réduire les chaînes dynamiquement.
ChainePointeurReceptrice = String$(20, "X")
Et enfin, on appelle la fonction.
LongueurEffective contiendra donc 10
ChainePointeurReceptrice contiendra C:\WINDOWS
le 20 correspond simplement à la place qu'on accepte de laisser à l'API pour stocker la chaîne. C'est donc le même ' chiffre que lors du remplissage préparatoire de la chaîne (ChainePointeurReceptrice = String$(20, "X")). Par contre, dans les exemples, on voit toujours que la chaîne est remplie avec des codes ASCII 0 (à la place du X de l'exemple di dessus). Ca ne me paraît pas judicieux, car ensuite la chaîne réceptrice va toujours être de 255 caractères : La fonction TRIM qui enlève les espaces de gauche et de droite reste inopérante. Je préconise donc plutôt ChainePointeurReceptrice = String$(20, 32), ou 32 est le code ASCII de l'espace, et qui, lui, est retirable grâce à la fonction Trim.
LongueurEffective = DossierWindows(ChainePointeurReceptrice, 20)
Cet exemple utilise une fonction API des plus simples. Elle permet de voir ou non le curseur de la souris. (x = ShowCursor(False) la cache, et x = ShowCursor(True) la montre)
Private Declare Function ShowCursor Lib
"user32" (ByVal bshow As Long) As Long
Private Sub Détail_Click()
Dim x
x = ShowCursor(False)
MsgBox "Plus de souris..."
x = ShowCursor(True)
End Sub
Dans la section déclaration du module
Attention : Le Declare [Sub|Function] DOIT se trouver dans la section déclaration d'un module indépendant. Si on le place dans la section déclaration d'un module de formulaire, ça ne marche pas (J'ai testé)
Declare Function wu_GetWindowsDirectory Lib "kernel32" Alias "GetWindowsDirectoryA" (ByVal lpBuffer As String, ByVal nSize As Long) As Long
Dans un module
Function ap_GetWindowsDir() As Variant
Dim strWindowsDir As String
Dim lngLength As Long
Dim lngResult As Long
'-- Set up buffer.
strWindowsDir = String$(255, 0)
lngLength = 255
'-- Make the call.
lngResult = wu_GetWindowsDirectory(strWindowsDir, lngLength)
'-- Clean up and assign the value.
ap_GetWindowsDir = Left(strWindowsDir, InStr(1, strWindowsDir, Chr(0)) - 1)
End Function
Appel de la foncion personnalisée
Il suffit ensuite d'appeler la fonction personnalisée ap_GetWindowsDir() pour avoir en retour la chaîne de caractères contenant le path de Windows.
La fonction API GetTickCount de kernel32 permet de connaître le temps en millisecondes depuis que Windows (ou lordinateur) est allumé.
Comme cette valeur change toutes les millisecondes, il faut bien sûr lappeler plusieurs fois, la stocker dans des variables temporaires, etc...
Pourquoi pas aussi utiliser cette fonction pour déterminer des nombres aléatoires
Declare Function GetTickCount Lib "kernel32" () As Long
MsgBox GetTickCount
Fonctionne uniquement en 32 bits (Windows 95). Dans cette fonction, on appelle directement l'API, sans passer pas une fonction personnalisée (cf nom de l'utilisateur courant)
Declare Function mciExecute Lib "winmm.dll" (ByVal lpstrcommand As String) As Long
Sub Test()
Dim x
x = mciExecute("Play C:\windows\msremind.wav")
End Sub
Declare Function JouerUnSon Lib "winmm.dll" Alias "mciExecute" (ByVal lpstrcommand As String) As Long
Sub Test()
Dim x
x = JouerUnSon("Play C:\windows\msremind.wav")
End Sub
Access 2 seulement
Il faut 2 choses : Installer la déclaration de la fonction d'appel dans un module quelconque :
Declare Function sndPlaySound Lib "mmsystem" (ByVal lpszSoundName As String, ByVal fuOptions As Integer) As Integer
Appeler cette routine avec une syntaxe correcte depuis n'importe oú :
VariableQuelconque = sndPlaySound("C:\chemin\fichier.wav", 1)
Ces 3 fonctions sont issues de Kernel32.DLL. Attention toutefois é la fonction DossierTemp qui, d'une part s'appelle à l'envers par rapport aux 2 autres, et qui contient en plus un backslash à la fin
Declare Function DossierWindows Lib "Kernel32.dll" Alias "GetWindowsDirectoryA" (ByVal Pointeur As String, ByVal Longueur As Long) As Long
Declare Function DossierSystem Lib "Kernel32.dll" Alias "GetSystemDirectoryA" (ByVal Pointeur As String, ByVal Longueur As Long) As Long
Declare Function DossierTemp Lib "Kernel32.dll" Alias "GetTempPathA" (ByVal Longueur As Long, ByVal Pointeur As String) As Long
Sub test()
Dim Resultat As Long
Dim PointeurChaine As String
PointeurChaine = String$(255, 32)
Resultat = DossierWindows(PointeurChaine, 255)
MsgBox PointeurChaine
Resultat = DossierSystem(PointeurChaine, 255)
MsgBox PointeurChaine
Resultat = DossierTemp(255, PointeurChaine)
MsgBox PointeurChaine
End Sub
Declare Function RecupNomOrdinateur Lib "Kernel32.dll" Alias "GetComputerNameA" (ByVal lpbuffer As String, nsize As Long) As Long
Dim NomOrdinateur As String
Dim Resultat As Long
NomOrdinateur = String$(255, 32)
Resultat = RecupNomOrdinateur(NomOrdinateur, 255)
MsgBox NomOrdinateur
Cette fonction permet de récupérer non pas l'utilisateur Access (que l'on peut simplement obtenir avec CurrentUser), mais bien le nom d'utilisateur que l'on rentre lorsqu'on arrive dans Windows :
Declare Function RecupNomUtilisateur Lib "advapi32.dll" Alias "GetUserNameA" (ByVal lpBuffer As String, nSize As Long) As Long
Function NomUtilisateur() As String
Dim StrNomUtilisateur As String
Dim Resultat As Long ' Contiendra simplement 1 si l'appel s'est bien déroulé
StrNomUtilisateur = String$(255, 0)
Resultat = RecupNomUtilisateur(StrNomUtilisateur, 255)
If Resultat = 1 Then
NomUtilisateur = StrNomUtilisateur
Else
NomUtilisateur = "UTILISATEUR INCONNU"
End If
End Function
Sub Test()
MsgBox NomUtilisateur
End Sub