C'est en effet possible, mais c'est un peu bricolé et cela nécessite deux implémentations complètement différentes selon la version de Windows. Pour les deux méthodes, vous devez configurer votre bouton d'alimentation pour mettre l'ordinateur en veille dans vos options d'alimentation.
Windows XP et inférieur :
Vous devez écraser le fichier de la fenêtre principale de votre programme. WndProc
fonction. Dans les IDE qui ne prennent pas en charge cette fonction de manière native, on peut utiliser la fonction suivante SetWindowLong
dans l'API user32. Dans votre WndProc
écoutez un WM_POWERBROADCAST (0x218)
message. Si vous recevez un message avec wParam de PBT_APMQUERYSUSPEND (0x0)
appelle la fonction souhaitée et retourne ensuite BROADCAST_QUERY_DENY (0x424D5144)
au lieu d'appeler la base WndProc
fonction. Exemple de code :
//At program start
//GWL_WNDPROC = -4
oldWndProc = SetWindowLong(this.hWnd, GWL_WNDPROC, &MyWndProc)
//In MyWndProc(hWnd, wMsg, wParam, lParam)
//WM_POWERBROADCAST = 0x218
//PBT_APMQUERYSUSPEND = 0x0
//BROADCAST_QUERY_DENY = 0x424D5144
if wMsg = WM_POWERBROADCAST && wParam = PBT_APMQUERYSUSPEND (
//CALL YOUR FUNCTION HERE!
return BROADCAST_QUERY_DENY
)
return CallWindowProc(oldWndProc, hWnd, wMsg, wParam, lParam)
//Before exiting
SetWindowLong(Me.hWnd, GWL_WNDPROC, oldWndProc)
Windows Vista et plus : (merci à Remy Lebeau de m'avoir mis sur la bonne voie)
Vous devez remplacer WndProc
comme pour XP, mais aussi appeler SetThreadExecutionState
dans l'API de kernel32 pour désactiver le mode veille et RegisterPowerSettingNotification
dans l'API user32 pour écouter les notifications d'alimentation avancées. Vous écouterez, en particulier, la fonction GUID_SYSTEM_AWAYMODE
qui est envoyée lorsqu'il a été demandé au système de se mettre en veille mais qu'il n'a pas pu le faire. Pour convertir facilement une chaîne de caractères en un LPCGUID
vous pouvez utiliser UuidFromStringA
dans l'API rpcrt4.dll. Exemple de code :
typedef struct UUID{
int d1, d2, d3, d4
} LPCGUID;
//At program start
//GWL_WNDPROC = -4
//ES_CONTINUOUS = 0x80000000
//ES_SYSTEM_REQUIRED = 0x1
//ES_AWAYMODE_REQUIRED = 0x40
//GUID_SYSTEM_AWAYMODE = "98a7f580-01f7-48aa-9c0f-44352c29e5C0"
LPCGUID uid;
oldWndProc = SetWindowLong(this.hWnd, GWL_WNDPROC, &MyWndProc)
SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_AWAYMODE_REQUIRED)
UuidFromStringA(*(GUID_SYSTEM_AWAYMODE), uid)
ps = RegisterPowerSettingNotification(this.hWnd, uid, 0)
//In MyWndProc(hWnd, wMsg, wParam, lParam)
//WM_POWERBROADCAST = 0x218
//PBT_POWERSETTINGCHANGE = 0x8013
if wMsg = WM_POWERBROADCAST && wParam = PBT_POWERSETTINGCHANGE (
//CALL YOUR FUNCTION HERE!
//You can additionally extract data from the lParam to verify
//this is the notification you're waiting for (see below)
)
return CallWindowProc(oldWndProc, hWnd, wMsg, wParam, lParam)
//Before exiting
SetWindowLong(Me.hWnd, GWL_WNDPROC, oldWndProc)
UnregisterPowerSettingNotification(ps)
Cette méthode a pour effet secondaire d'éteindre votre écran physique (ce qui n'est pas un problème sur une machine sans tête), et aussi de verrouiller éventuellement votre session. Assurez-vous de désactiver la demande de mot de passe après le sommeil pour éviter cela. Vous trouverez d'autres informations utiles sur RegisterPowerSettingNotification
disponible sur aquí qui montre comment extraire des informations du lParam
en su WndProc
au cas où vous souhaiteriez obtenir des informations supplémentaires sur la notification. Amusez-vous bien ;)