2010-02-05 13 views
12

हाय मैं खोज रहा हूं लेकिन मुझे जवाब नहीं मिल रहा है। मुझे कैसे पता चलेगा कि स्क्रीन कब चल रही है या चालू है। SystemEvents.PowerModeChanged नहीं है। मुझे पता है कि प्रदर्शन/स्क्रीन घटनाएँसी # स्क्रीन/डिस्प्ले बंद या चालू होने पर ईवेंट कैसे प्राप्त करें?

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; 
     } 

संपादित

पुनः प्राप्त करने के शायद मैं अपने उत्कटता व्याख्या कर सकते हैं न, इसलिए वहाँ शायद एक बेहतर समाधान है। मेरे पास एक दोहरी बाध्यकारी डब्ल्यूसीएफ सेवा चल रही है। यह एक संग्रह (पोर्टेबल टैबलेट पीसी) पर चल रहा है। मैं चाहता हूं कि जब उपयोगकर्ता निष्क्रिय समय के लिए काम करना बंद कर देता है, तो कनेक्शन तत्काल बंद हो जाता है, और जब कंप्यूटर निष्क्रिय से वापस आ रहा है, तो वह तुरंत पुनः कनेक्ट हो जाता है। टॉम से Application Idle on Code project का विचार पहले से ही एक अच्छा विचार है। कम बिजली की खपत, बेहतर। स्टार्टअप जितना संभव हो सके तेज़ होना चाहिए।

उत्तर

7

इस ब्लॉग को देखें here जो आपको प्राप्त करने की कोशिश कर रहे हैं, जो आपको करने में मदद करेगा। इसके अलावा आप कुछ इस तरह आप के लिए यह करने के लिए एक कस्टम ईवेंट बनाने की जरूरत है:

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)); 
    } 

} 

संपादित करें: कैसे घटनाओं को पुनः प्राप्त करने रूप मनु यकीन नहीं था, इस संपादित एक नमूना शामिल होंगे नीचे दिखाए गए अनुसार इस वर्ग का उपयोग कैसे करें इस पर कोड।

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!"); 
     } 

    } 
} 

इस कोड को देखते हुए, और एहसास है कि कुछ बहुत सही नहीं था के बाद, यह मुझ पर लगा कि मनु एक तरह से मॉनिटर की शक्ति का दर्जा जो उपलब्ध नहीं है पता लगाने के लिए प्रणाली पूछताछ के लिए देख रहा था, लेकिन, कोड प्रोग्रामेटिक रूप से दिखाता है, मॉनीटर को चालू/बंद/स्टैंडबाय चालू किया जा सकता है, साथ ही साथ एक ईवेंट ट्रिगर किया जा सकता है, लेकिन वह चाहता था कि वह एक फॉर्म के WndProc में हुक करने और संदेश की स्थिति को इंगित करने के लिए संदेश को संसाधित करने में सक्षम हो निगरानी करें ... अब, इस बिंदु पर, मैं इस पर अपनी राय व्यक्त करने जा रहा हूं।

मुझे 100% यकीन नहीं है कि यह किया जा सकता है या क्या विंडोज वास्तव में एक प्रसारण संदेश भेजता है जैसे 'हे! मॉनीटर सो जाएगा 'या' अरे! मॉनिटर पावरिंग है ', मुझे यह कहने में डर है कि मॉनीटर वास्तव में विंडोज़ को कुछ सॉफ़्टवेयर सिग्नल नहीं भेजते हैं ताकि यह सूचित किया जा सके कि यह सो/ऑफ/ऑन हो रहा है। अब अगर किसी के पास कोई सुझाव, संकेत, इसके बारे में सुराग है, तो अपनी टिप्पणी पोस्ट करने के लिए स्वतंत्र महसूस करें ...

स्क्रीनसेवर टैब के हिस्से के रूप में एनर्जी स्टार सॉफ़्टवेयर जो कि जब आप कहीं भी डेस्कटॉप पर राइट क्लिक करते हैं, तो पॉप -अप मेनू प्रकट होता है, 'गुण' पर बायाँ क्लिक करें, एक 'प्रदर्शन' संवाद बॉक्स दिखाई देता है, विभिन्न टैब पृष्ठों के साथ, 'स्क्रीनसेवर' पर बायाँ क्लिक करें, 'मॉनिटर पावर' समूह बॉक्स के हिस्से के रूप में 'पावर' बटन पर क्लिक करें, डायलॉग बॉक्स का वह हिस्सा, किसी भी तरह से विंडोज सबसिस्टम (ग्राफिक्स कार्ड?/एनर्जी स्टार ड्राइवर?) को ट्रिगर करता है ताकि मॉनीटर की पावर सेविंग कार्यक्षमता पर स्विच करने के लिए हार्डवेयर सिग्नल भेज सके ... (मॉनीटर जो ब्रांड नए नहीं हैं यह डिफ़ॉल्ट AFAIK द्वारा सक्षम है ... इस धारणा को खारिज करने के लिए स्वतंत्र महसूस करें ...)

जब तक कोई अनियंत्रित नहीं होता डी एपीआई कहीं भी एम्बेडेड और एनर्जी-पावर सॉफ़्टवेयर ड्राइवर के भीतर गहरी दफनाया गया है (एक एपीआई निश्चित रूप से वास्तव में ट्रिगर हुआ है कि 'पावर' बटन पर क्लिक करने से मॉनीटर को सिग्नल भेज दिया जाता है जिसमें पावर मोड वास्तव में परिणामस्वरूप सक्रिय हो जाता है!) तो शायद, कहा गया फॉर्म आवेदन की पृष्ठभूमि में एक थ्रेड चलाकर, अभी तक अज्ञात कार्यक्षमता या पावर स्थिति की जांच करने के लिए एक एपीआई पूछताछ करने के लिए मतदान - वहां कुछ ऐसा होना चाहिए जो केवल माइक्रोसॉफ्ट के बारे में जानता हो ... आखिरकार, एनर्जी स्टार ने माइक्रोसॉफ्ट को मॉनिटर पर पावर सेविंग मोड को ट्रिगर करने का तरीका दिखाया, निश्चित रूप से यह एक तरह से सड़क नहीं है? या यह है?

क्षमा मनु अगर मैं आगे मदद नहीं कर सकते .... :(

संपादित # 2: मैं क्या मैं संपादन में पहले लिखा था और किया के बारे में सोचा चारों ओर से खुदाई एक जवाब के लिए पक्ष का एक सा और मुझे लगता है कि मैं जवाब के साथ आया था, लेकिन सबसे पहले, मेरे सिर में एक विचार आया, इस दस्तावेज़ को here देखें - 'terranovum.com' से एक पीडीएफ दस्तावेज़, सुराग (या तो मैंने सोचा ...) रजिस्ट्री में था, दस्तावेज़ के अंतिम पृष्ठ पर अंतिम दो रजिस्ट्री कुंजियों का उपयोग करते हुए निष्क्रिय ऑफसेट को जानने के लिए, CodeProject आलेख के साथ निर्दिष्ट ऑफसेट, और CodeProject आलेख के संयोजन के साथ, यह निर्धारित करना आसान होगा कि मॉनिटर स्टैंडबाय में कब जाता है , सरल लगता है या तो मैंने सोचा, मनु उस धारणा को पसंद नहीं करेंगे ....

Google के साथ आगे की जांच मुझे इस निष्कर्ष तक ले जाती है, उत्तरविनिर्देश DPMS (प्रदर्शन पावर प्रबंधन सिग्नलिंग) के विस्तार में है, अब यह सवाल उठता है , आप वीईएसए बायोस पर उस सिग्नलिंग से पूछताछ कैसे करते हैं, अब, बहुत सारे आधुनिक ग्राफिक्स कार्डों में यह है कि वीईएसए बायोस इसमें फिट है, इसलिए वहां एक हार्डवेयर पोर्ट होना चाहिए जहां आप इस मार्ग का उपयोग करके पिन के मूल्यों को पढ़ सकते हैं InpOut32 के उपयोग की आवश्यकता होगी या यदि आपके पास 64 बिट विंडोज है, तो पिनवोक के माध्यम से InpOut64 है। असल में यदि आप टर्बो सी या टर्बो पास्कल का उपयोग कर याद कर सकते हैं, (डॉस के लिए 16 बिट दोनों) वहां नियमित रूप से इनपोर्ट/आउटपोर्ट कहा जाता है या हार्डवेयर बंदरगाह पढ़ने के लिए या यहां तक ​​कि जीडब्ल्यूबीएएसआईसी पीक/पोक का उपयोग करके भी किया जाता है। यदि हार्डवेयर पोर्ट का पता पाया जा सकता है, तो क्षैतिज सिंक और वर्टिकल सिंक की जांच करके मॉनीटर स्टैंडबाय/पावर ऑफ/निलंबित/निर्धारित करने के लिए मूल्यों से पूछताछ की जा सकती है, यह मुझे लगता है कि यह अधिक विश्वसनीय समाधान है। .. विस्तृत उत्तर के लिए

क्षमा चाहते हैं लेकिन लगा कि मैं नीचे मेरे विचारों को लिखना पड़ा ....

अभी भी वहाँ आशा है कि मनु नहीं है :);)

+1

नहीं वास्तव में, कैसे करना है आप घटनाओं को पुनः प्राप्त। कैसे पता चलेगा कि यह चालू है या बिजली बंद है? - 10 मिनट के बाद मेरी स्क्रीन मंद हो रही है। - 15 मिनट के बाद मेरी स्क्रीन बंद हो जाती है। - मैं माउस को ले जाता हूं, स्क्रीन चालू होती है। इन घटनाओं को कैसे प्राप्त करें? (सत्र घटनाओं नहीं) – Manu

+0

@ मॅनू: मुझे इस जवाब को संपादित करने के लिए घटनाओं को पुनर्प्राप्त करने का नमूना शामिल करने दें .... – t0mm13b

+0

वाह, रुचि। मैंने नहीं सोचा था कि यह गोन इतना जटिल हो गया है। मैं एक विशेषज्ञ नहीं हूँ, निश्चित रूप से रजिस्ट्री के साथ नहीं। तो मैं उस पर छूने से थोड़ा डर रहा हूँ। "एप्लिकेशन निष्क्रिय" पहले से ही एक अच्छा विचार है। – Manu

-1
/// <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; 
    } 
} 
+2

कृपया अपने कोड पर कुछ टिप्पणी जोड़ें (यह कोड समस्या को हल क्यों करता है)। एक स्पष्टीकरण के बिना, यह एक जवाब नहीं है। – Artemix

3

लापता हिस्सा था कि मैं घटनाओं के लिए पंजीकरण नहीं किया था।

मिले 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; 
} 
+0

आपके द्वारा प्रदान किया गया लिंक अब तक टूटा हुआ है, और आपके उदाहरण कोड में पहली पंक्ति के मान गुम हैं। तो बस किसी और के लिए जो भविष्य में इसका सामना कर सकता है: GUID_MONITOR_POWER_ON मान (02731015-4510-4526-99e6-e5a17ebd1aea) के लिए मैंने [इस लिंक] का उपयोग किया [https://msdn.microsoft.com/en-us/ लाइब्रेरी/विंडोज़/डेस्कटॉप/एचएच 448380 (वी = बनाम .5) .aspx) संदर्भ के रूप में, और 0 DEVICE_NOTIFY_WINDOW_HANDLE के मान के लिए। –

संबंधित मुद्दे