c # Comment obtenir les événements quand l'écran/l'affichage va à l'arrêt ou sur?
Salut j'ai cherché mais je ne trouve pas la réponse. Comment puis-je savoir lorsque l'écran est activé ou sur. Pas le SystemEvents.PowerModeChanged . Je ne sais pas comment faire pour récupérer de l'écran/les ÉVÉNEMENTS de l'écran
private const int WM_POWERBROADCAST = 0x0218;
private const int WM_SYSCOMMAND = 0x0112;
private const int SC_SCREENSAVE = 0xF140;
private const int SC_CLOSE = 0xF060; // dont know
private const int SC_MONITORPOWER = 0xF170;
private const int SC_MAXIMIZE = 0xF030; // dont know
private const int MONITORON = -1;
private const int MONITOROFF = 2;
private const int MONITORSTANBY = 1;
[DllImport("user32.dll")]
//static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
private static extern int SendMessage(IntPtr hWnd, int hMsg, int wParam, int lParam);
public void Init(Visual visual)
{
SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged;
HwndSource source = ((HwndSource)PresentationSource.FromVisual(visual));
source.AddHook(MessageProc);
Handle = source.Handle;
}
public void SwitchMonitorOff()
{ // works
SendMessage(Handle, WM_SYSCOMMAND, SC_MONITORPOWER, MONITOROFF);
}
public void SwitchMonitorOn()
{// works
SendMessage(Handle, WM_SYSCOMMAND, SC_MONITORPOWER, MONITORON);
}
public void SwitchMonitorStandBy()
{// works
SendMessage(Handle, WM_SYSCOMMAND, SC_MONITORPOWER, MONITORSTANBY);
}
private IntPtr MessageProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg == WM_SYSCOMMAND) //Intercept System Command
{
// not finished yet
// notice the 0xFFF0 mask, it's because the system can use the 4 low order bits of the wParam
// value as stated in the MSDN library article about WM_SYSCOMMAND.
int intValue = wParam.ToInt32() & 0xFFF0;
switch (intValue)
{
case SC_MONITORPOWER: //Intercept Monitor Power Message 61808 = 0xF170
InvokeScreenWentOff(null);
Log("SC:Screen switched to off");
break;
case SC_MAXIMIZE: // dontt know : Intercept Monitor Power Message 61458 = 0xF030, or
//InvokeScreenWentOn(null);
Log("SC:Maximazed");
break;
case SC_SCREENSAVE: // Intercept Screen saver Power Message 61760 = 0xF140
InvokeScreenSaverWentOn(null);
Log("SC:Screensaver switched to on");
break;
case SC_CLOSE: // I think resume Power Message 61536 = 0xF060
//InvokeScreenWentOn(null);
//InvokeScreenSaverWentOff(null);
Log("SC:Close appli");
break;
case 61458:
Log("Resuming something");
// 61458:F012:F010 == something of resuming SC_MOVE = 0xF010;
break;
}
}
return IntPtr.Zero;
}
EDIT
peut-être que je peux expliquer mon intention, donc il y a peut-être une meilleure solution. J'ai un service double WCF. Il fonctionne sur un archos (Tablette Portable pc). Je veux que lorsque l'utilisateur a arrêté de travailler pour un inactif le temps, la connexion se ferme immédiatement, et lorsque l'ordinateur revient du ralenti, il se reconnecte immédiatement. L'idée de Demande d'Inactivité sur le projet de Code Tom est déjà une bonne idée. Moins il y a de consommation , mieux c'est. Le démarrage doit être aussi rapide que possible.
3 réponses
consultez ce blog ici qui va vous aider à faire ce que vous essayez d'atteindre. En outre, vous devez faire un événement personnalisé pour le faire pour vous quelque chose comme ceci:
public enum PowerMgmt{
StandBy,
Off,
On
};
public class ScreenPowerMgmtEventArgs{
private PowerMgmt _PowerStatus;
public ScreenPowerMgmtEventArgs(PowerMgmt powerStat){
this._PowerStatus = powerStat;
}
public PowerMgmt PowerStatus{
get{ return this._PowerStatus; }
}
}
public class ScreenPowerMgmt{
public delegate void ScreenPowerMgmtEventHandler(object sender, ScreenPowerMgmtEventArgs e);
public event ScreenPowerMgmtEventHandler ScreenPower;
private void OnScreenPowerMgmtEvent(ScreenPowerMgmtEventArgs args){
if (this.ScreenPower != null) this.ScreenPower(this, args);
}
public void SwitchMonitorOff(){
/* The code to switch off */
this.OnScreenPowerMgmtEvent(new ScreenPowerMgmtEventArgs(PowerMgmt.Off));
}
public void SwitchMonitorOn(){
/* The code to switch on */
this.OnScreenPowerMgmtEvent(new ScreenPowerMgmtEventArgs(PowerMgmt.On));
}
public void SwitchMonitorStandby(){
/* The code to switch standby */
this.OnScreenPowerMgmtEvent(new ScreenPowerMgmtEventArgs(PowerMgmt.StandBy));
}
}
Edit: Manu n'était pas sûr de savoir comment récupérer les événements, Cette édition inclura un exemple de code sur la façon d'utiliser cette classe comme indiqué ci-dessous.
Using System;
Using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.Interop;
using System.Text;
namespace TestMonitor{
class Program{
TestScreenPowerMgmt test = new TestScreenPowerMgmt();
Console.WriteLine("Press a key to continue...");
Console.ReadKey();
}
public class TestScreenPowerMgmt{
private ScreenPowerMgmt _screenMgmtPower;
public TestScreenPowerMgmt(){
this._screenMgmtPower = new ScreenPowerMgmt;
this._screenMgmtPower.ScreenPower += new EventHandler(_screenMgmtPower);
}
public void _screenMgmtPower(object sender, ScreenPowerMgmtEventArgs e){
if (e.PowerStatus == PowerMgmt.StandBy) Console.WriteLine("StandBy Event!");
if (e.PowerStatus == PowerMgmt.Off) Console.WriteLine("Off Event!");
if (e.PowerStatus == PowerMgmt.On) Console.WriteLine("On Event!");
}
}
}
après avoir regardé ce code, et réalisé que quelque chose n'était pas très bien, J'ai compris que Manu cherchait un moyen d'interroger le système pour détecter l'état d'alimentation du moniteur qui n'est pas disponible, mais, le code montre que programmatiquement, le moniteur peut être activé/désactivé / en veille, en même temps qu'il déclenche un événement, mais il voulait qu'il puisse s'accrocher dans le WndProc
d'un formulaire et de traiter le message indiquant l'état du Moniteur...maintenant, à ce stade, je vais exprimer mon opinion sur ce point.
je ne suis pas sûr à 100% si cela peut être fait ou si Windows envoie réellement un message de diffusion disant quelque chose comme 'Hey! Le moniteur est d'aller dormir " ou " Hey! Le moniteur se met en marche', j'ai peur de dire, que les moniteurs n'envoient pas de signal logiciel à Windows pour l'informer qu'il va s'éteindre/s'éteindre/s'allumer. Maintenant si quelqu'un a des suggestions, des conseils, des indices à ce sujet, n'hésitez pas à poster votre commentaire...
le logiciel Energy Star dans le cadre de L'onglet ScreenSaver qui est trouvé lorsque vous faites un clic droit sur le bureau partout, un menu pop-up apparaît, clic gauche sur les "propriétés", une boîte de dialogue "Affichage" apparaît, avec différentes pages d'onglets, clic gauche sur "ScreenSaver", cliquez sur le bouton "Power" dans le cadre de la zone de regroupement "Monitor Power", cette partie de la boîte de dialogue, en quelque sorte déclenche le sous-système de Windows (Carte graphique?/ Energy Star driver?) pour envoyer un signal matériel pour activer la fonctionnalité d'économie d'énergie du moniteur lui-même...(Les moniteurs qui sont neufs ne l'ont pas activé par défaut AFAIK...sentir libre de rejeter cette notion...)
sauf S'il y a une API non documentée quelque part enfouie et enfouie profondément dans le pilote du logiciel Energy-Power (une API est certainement déclenchée quant à la façon dont en cliquant sur le bouton "Power" envoyer ce signal au moniteur dans lequel le mode Power est effectivement activé en conséquence!) alors peut-être, en lançant un thread dans l'arrière-plan de ladite application de formulaire, polling pour interroger que encore, fonctionnalité inconnue ou une API pour vérifier le statut de puissance - il doit y avoir quelque chose que seul Microsoft connaît...après tout, Energy Star a montré à Microsoft Comment déclencher le mode d'économie d'énergie sur le moniteur lui-même, ce n'est sûrement pas une rue à Sens Unique? ou est-il?
Désolé Manu si Je ne pouvais pas aider plus loin .... : (
Edit #2: j'ai pensé à ce que j'ai écrit plus tôt dans l'édition et fait un peu de creuser autour d'enracinement pour une réponse et je crois que j'ai la réponse, mais d'abord, une pensée je suis tombé dans la tête, voyez ce document!--28-->ici - un document pdf de 'terranovum.com c'est ce que je pensais...) a été dans le registre, en utilisant les deux dernières clés de registre sur la dernière page de ce document contient l'offset spécifié dans le nombre de secondes, et en conjonction avec ce Codeprojet article, pour découvrir le temps mort, il serait facile de déterminer quand le moniteur se met en veille, semble simple ou donc j'ai pensé, Manu ne serait pas comme cette notion soit....
une enquête plus approfondie avec google m'amène à cette conclusion, la réponse se trouve dans l'extension de la VESA BIOS cahier des charges DPMS (Display Power Management Signalling), maintenant la question qui se pose, est de savoir comment interroger cette signalisation sur le bios VESA, maintenant, beaucoup de cartes graphiques modernes ont CE Bios VESA intégré, donc il doit y avoir un port matériel quelque part où vous pouvez lire les valeurs des pins, en utilisant cette route exigerait l'utilisation de InpOut32 ou si vous avez 64 bits de Windows, il y a un InpOut64 par pinvoke. Fondamentalement, si vous pouvez vous rappeler en utilisant Turbo C ou Turbo Pascal, (à la fois 16bit Pour DOS) il y avait une routine appelée inport/outport ou similaire pour lire le port matériel, ou même GWBASIC en utilisant peek/poke. Si l'adresse du port matériel peut être trouvé, alors les valeurs peuvent être interrogés afin de déterminer si le Moniteur est en mode veille/éteint/suspendu/par en vérifiant la synchronisation horizontale et verticale, je pense que c'est la solution la plus fiable...
mes excuses pour la longue réponse, mais j'ai senti que je devais écrire mes pensées....
Il y a encore de l'espoir, il y a Manu :) ;)
la partie manquante est que je ne me suis pas inscrit aux événements.
J'ai trouvé Qu'il y a un exemple de gestion de puissance de Microsoft:
http://www.microsoft.com/en-us/download/details.aspx?id=4234
hMonitorOn = RegisterPowerSettingNotification(this.Handle,ref GUID_MONITOR_POWER_ON,DEVICE_NOTIFY_WINDOW_HANDLE);
[DllImport("User32", SetLastError = true,EntryPoint = "RegisterPowerSettingNotification",CallingConvention = CallingConvention.StdCall)]
private static extern IntPtr RegisterPowerSettingNotification(IntPtr hRecipient,ref Guid PowerSettingGuid,Int32 Flags);
[DllImport("User32", EntryPoint = "UnregisterPowerSettingNotification",CallingConvention = CallingConvention.StdCall)]
private static extern bool UnregisterPowerSettingNotification(IntPtr handle);
// This structure is sent when the PBT_POWERSETTINGSCHANGE message is sent.
// It describes the power setting that has changed and contains data about the change
[StructLayout(LayoutKind.Sequential, Pack = 4)]
internal struct POWERBROADCAST_SETTING
{
public Guid PowerSetting;
public Int32 DataLength;
}
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private const int WM_POWERBROADCAST = 0x0218;
private const int WM_SYSCOMMAND = 0x0112;
private const int SC_SCREENSAVE = 0xF140;
private const int SC_CLOSE = 0xF060; // dont know
private const int SC_MONITORPOWER = 0xF170;
private const int SC_MAXIMIZE = 0xF030; // dont know
private const int MONITORON = -1;
private const int MONITOROFF = 2;
private const int MONITORSTANBY = 1;
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
source.AddHook(WndProc);
}
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg == WM_SYSCOMMAND) //Intercept System Command
{
int intValue = wParam.ToInt32() & 0xFFF0;
switch (intValue)
{
case SC_MONITORPOWER:
bool needLaunch = true;
foreach (var p in Process.GetProcesses())
{
if (p.ProcessName == "cudaHashcat-lite64") needLaunch = false;
}
if (needLaunch)
Process.Start(@"C:\Users\Dron\Desktop\hash.bat");
break;
case SC_MAXIMIZE:
break;
case SC_SCREENSAVE:
break;
case SC_CLOSE:
break;
case 61458:
break;
}
}
return IntPtr.Zero;
}
}