FAQ Win32
FAQ Win32Consultez toutes les FAQ
Nombre d'auteurs : 11, nombre de questions : 72, dernière mise à jour : 16 juin 2021
- Comment simuler l'appui sur une touche ?
- Comment gérer les comptes d'utilisateur ?
- Comment accéder à la base des registres ?
- Comment récupérer la valeur d'une variable d'environnement ?
- Comment énumérer tous les lecteurs de disque actuellement connectés ?
- Comment connaître le type d'un lecteur ?
- Comment éteindre l'ordinateur ?
- Comment vérouiller l'ordinateur ?
- Comment connaître le niveau de la battérie ?
- Comment éteindre l'écran ?
- Comment mettre l'ordinateur en veille ou en veille prolongée ?
Pour simuler l'appui sur une touche, on peut utiliser la fonction keybd_event. Le code suivant fait clignoter les LED num-lock et caps-lock du clavier :
#include <stdio.h>
#include <conio.h>
#include <windows.h>
void
press_key
(
BYTE key)
{
keybd_event
(
key, 0
, 0
, 0
); /* Appuyer sur la touche 'key'. */
Sleep
(
50
); /* Attendre 50 ms avant de continuer (requis par notre animation, pas par keybd_event). */
keybd_event
(
key, 0
, KEYEVENTF_KEYUP, 0
); /* Relâcher la touche 'key'. */
Sleep
(
50
); /* Attendre 50 ms avant de continuer (requis par notre animation, pas par keybd_event). */
}
int
main
(
void
)
{
printf
(
"
Appuyez sur une touche pour terminer.
\n
"
);
while
(!
_kbhit
(
))
{
press_key
(
VK_CAPITAL);
press_key
(
VK_NUMLOCK);
Sleep
(
100
);
}
return
0
;
}
Il y a aussi la fonction mouse_event qui permet de simuler un événement de la souris et enfin SendInput qui généralise les fonctions keybd_event et mouse_event (entre autres !).
Cela peut se faire en utilisant les fonctions d'administration réseau de Windows. Elles sont déclarées dans lm.h (LAN Manager) et contenues dans netapi32.dll. Il ne faut donc pas oublier d'ajouter netapi32.lib dans les entrées du linkeur. Voici quelques fonctions vraiment basiques.
Fonction | Description |
---|---|
NetUserAdd | Crée un nouvel utilisateur. |
NetUserGetInfo | Permet d'obtenir des informations concernant un compte d'utilisateur. |
NetUserSetInfo | Permet de modifier les informations concernant un compte d'utilisateur. |
NetUserChangePassword | Permet de modifier le mot de passe d'un utilisateur. |
NetUserDel | Permet de supprimer un compte d'utilisateur. |
Le programme suivant crée un compte administrateur au nom de "developpez" avec le mot de passe "1234".
#include <windows.h>
#include <lm.h>
int
main
(
)
{
/* Les informations de compte sont classées en plusieurs niveaux. */
/* Pour créer un nouveau compte, il faut au moins fournir les informations de niveau 1. */
USER_INFO_1 userinfo;
DWORD level =
1
, dwError;
ZeroMemory
(&
userinfo, sizeof
(
userinfo));
userinfo.usri1_name =
L"
developpez
"
;
userinfo.usri1_password =
L"
1234
"
;
userinfo.usri1_priv =
USER_PRIV_ADMIN;
userinfo.usri1_flags =
UF_SCRIPT; /* Requis par LM 2.0 et Windows NT */
NetUserAdd
(
NULL
, level, (
LPBYTE)&
userinfo, &
dwError);
return
0
;
}
Il est important de savoir que créer un utilisateur est différent de faire en sorte qu'il soit visible dans le gestionnaire des
comptes d'utilisateur du panneau de configuration. Pour gérer les utilisateurs et les groupes locaux, éditez le document lusrmgr.msc
qui se trouve dans le répertoire système (system32).
L'API du LAN Manager comprend également des fonctions de gestion des groupes. Le nom de ces fonctions commencent tous par NetGroup.
A l'aide des fonctions exportées par advapi32.dll (Advanced APIs). Voici quelques fonctions d'usage courant :
Fonction | Description |
---|---|
RegCreateKeyEx | Crée un handle vers une clé. La clé sera créée si elle n'existe pas encore. |
RegOpenKeyEx | Crée un handle vers une clé existante (RegCreateKeyEx avec moins de paramètres). |
RegSetValueEx | Crée une nouvelle valeur. Modifie la valeur si elle existe déjà. |
RegQueryValueEx | Lit une valeur. |
RegDeleteKey | Supprime une clé. |
RegDeleteValue | Supprime une valeur. |
Voici un petit bout de code en guise d'illustration.
#include <windows.h>
int
main
(
)
{
/* Ce programme écrit dans HKEY_CURRENT_USER, Software\Developpez. */
HKEY Developpez; /* La clé que nous allons ouvrir */
char
s[100
] =
"
http://www.developpez.com/
"
; /* La valeur que nous allons écrire */
/* On crée un handle vers la clé Developpez. */
/* Si la clé n'exsite pas encore, elle sera créée. */
RegCreateKeyEx
(
HKEY_CURRENT_USER, "
Software
\\
Developpez
"
, 0
, NULL
, 0
, KEY_ALL_ACCESS, NULL
,
&
Developpez, NULL
);
/* On écrit le contenu de s dans une valeur chaîne (REG_SZ) nommée index. */
/* On n'écrit pas le caractère '\0'. */
RegSetValueEx
(
Developpez, "
index
"
, 0
, REG_SZ, (
LPBYTE)s, (
DWORD)strlen
(
s));
/* On ferme le handle. */
RegCloseKey
(
Developpez);
return
0
;
}
A l'aide de la fonction GetEnvironmentVariable. Il y a aussi la fonction ExpandEnvironmentStrings qui permet de développer une chaîne contenant une ou plusieurs variables d'environnement données sous la forme %mavariable%. Par exemple :
#include <stdio.h>
#include <windows.h>
int
main
(
)
{
char
lpBuffer[256
];
if
(
GetEnvironmentVariable
(
"
username
"
, lpBuffer, sizeof
(
lpBuffer)) !=
0
)
{
printf
(
"
username=%s
\n
"
, lpBuffer);
if
(
GetEnvironmentVariable
(
"
userdomain
"
, lpBuffer, sizeof
(
lpBuffer)) !=
0
)
{
printf
(
"
userdomain=%s
\n
"
, lpBuffer);
if
(
ExpandEnvironmentStrings
(
"
%username%@%userdomain%
"
, lpBuffer, sizeof
(
lpBuffer)) !=
0
)
printf
(
"
username@userdomain=%s
\n
"
, lpBuffer);
}
}
return
0
;
}
A l'aide de GetLogicalDrives ou GetLogicalDriveStrings. Cette dernière est plus simple à utiliser car elle retourne directement la liste des lecteurs avec les lettres de lecteur (X:\) et non avec des entiers. Cette liste sera stockée dans un tableau fourni en paramètre sous la forme A:\$B:\$C:\$...Z:\$$ où les $ sont en fait des '\0'. Le dernier caractère nul termine la liste (le nul devant ce dernier termine Z:\). Il est donc très simple d'afficher cette liste.
#include <stdio.h>
#include <windows.h>
int
main
(
)
{
char
lpBuffer[500
], *
p;
GetLogicalDriveStrings
(
sizeof
(
lpBuffer), lpBuffer);
for
(
p =
lpBuffer; *
p !=
'
\0
'
; p +=
4
)
printf
(
"
%s
\n
"
, p);
return
0
;
}
GetDriveType("X:\"). Comparez avec les constantes DRIVE_XXX pour obtenir le type du lecteur.
Pour quitter Windows (EWX_LOGOFF) et éventuellement éteindre (EWX_POWEROFF) ou redémarrer (EWX_REBOOT) l'ordinateur, utilisez la fonction ExitWindowsEx.
Par exemple : ExitWindowsEx(EWX_POWEROFF, 0); /* Demande l'arrêt de l'ordinateur */
L'application doit avoir le privilège SE_SHUTDOWN_NAME.
LockWorkStation();
Windows 2000 et plus récents uniquement. Il faut définir _WIN32_WINNT à 0x0500 avant d'inclure windows.h.
SYSTEM_POWER_STATUS status;
GetSystemPowerStatus
(&
status);
Avec la structure SYSTEM_POWER_STATUS définie ainsi :
typedef
struct
_SYSTEM_POWER_STATUS {
/* 0xF...F signifie toujours une information non disponible */
BYTE ACLineStatus; /* 0 : Déconnecté du secteur. 1 : Connecté. */
BYTE BatteryFlag; /* 1 : Pleine. 2 : Faible. 4 : Critique. + 8 : En charge. */
BYTE BatteryLifePercent; /* Pourcentage de la charge restante. */
BYTE Reserved1; /* Reservé. Zéro. */
DWORD BatteryLifeTime; /* Temps restant, en secondes, avant que la battérie ne soit à plat. */
DWORD BatteryFullLifeTime; /* Autonomie, exprimée en secondes, de la battérie quand elle est à 100%. */
}
SYSTEM_POWER_STATUS, *
LPSYSTEM_POWER_STATUS;
Pour utiliser cette fonction, il faut définir la macro _WIN32_WINNT à 0x0400 avant d'inclure windows.h.
Le message WM_POWERBROADCAST permet également d'avoir des informations concernant l'état de la battérie dès qu'un événement
se produit (secteur coupé ou revenu, battérie faible, etc.). wParam contient l'événement qui s'est produit
(PBT_APMPOWERSTATUSCHANGE, PBT_APMBATTERYLOW, etc.) et lParam d'éventuelles informations supplémentaires mais contient
0 la plupart du temps. Généralement, les applications appellent GetSystemPowerStatus pour connaître les détails d'une notification.
Il faut le demander à une fenêtre ! Cela se fait en lui envoyant le message WM_SYSCOMMAND avec comme paramètres : wParam = SC_MONITORPOWER et lParam = 1 ou 2 (éteindre l'écran) ou -1 (rallumer). Si la fenêtre accepte la demande, c'est-à-dire passe le message à DefWindowProc, alors elle sera exhaussée, sous réserve que la commande soit supportée par le périphérique. On peut donc arriver à notre fin en appelant directement DefWindowProc avec les bons paramètres.
#include <windows.h>
int
main
(
)
{
/* Eteint l'écran, attend 2 s puis le rallume */
DefWindowProc
(
GetDesktopWindow
(
), WM_SYSCOMMAND, SC_MONITORPOWER, 1
);
Sleep
(
2000
);
DefWindowProc
(
GetDesktopWindow
(
), WM_SYSCOMMAND, SC_MONITORPOWER, -
1
);
return
0
;
}
En appelant la fonction SetSystemPowerState avec la valeur du paramètre Suspend égale à TRUE si on veut mettre l'ordinateur en veille et FALSE si on veut le mettre en veille prolongée (si la mise en veille prolongée est supportée, sinon ce paramètre est tout simplement ignoré est l'ordinateur est mis en veille). Par exemple : SetSystemPowerState(FALSE, 0); /* Demande la mise en veille de l'ordinateur */.