2010-07-28 5 views
26

Ist es möglich zu erkennen, wenn der Deckel eines Laptops offen oder geschlossen ist? Nach dem, was ich gelesen habe, ist das nicht möglich, aber SO hat mir bisher geholfen mit dem Unmöglichen.Laptop-Deckelverschluss und Öffnung erkennen

Das einzige, was ich gefunden habe, dass in die richtige Richtung könnte ist ein MSDN blog post about IOCTLs needed to report power buttons. Ist es möglich, diese zu "schnüffeln", wenn das Betriebssystem sie anruft?

Ich benutze VB.NET, aber werde Vorschläge in jeder Sprache nehmen. Vielen Dank für Ihre Zeit und Ihren Rat.

Bearbeiten: Meine Software wird (eventuell) die Aktionen (basierend auf den Benutzereinstellungen) überschreiben, die beim Schließen des Deckels auftreten, so dass das Warten auf Aussetzen und andere Aktionen, die normalerweise beim Schließen des Deckels auftreten, nicht erfolgt eine Option.

+0

Ich bin wirklich neugierig, warum Sie das wollen. –

+0

Ich muss bestimmte Aktionen ausführen, wenn der Deckel geschlossen ist. Ich möchte zum Beispiel den Desktop sperren oder eine Datei anmelden, wenn der Deckel geschlossen und geöffnet wurde. Diese Übung ist nicht akademisch, ich kann den genauen Grund zu diesem Zeitpunkt aufgrund der NDA nicht offen legen. Es tut uns leid. – Brad

+0

Ich bin kein Experte, aber ich denke, auf OS-Anrufe zu hören würde COM oder P/INVOKE einer Art erfordern. Möglicherweise möchten Sie diese Tags hinzufügen, um eine sachkundigere Leserschaft zu erhalten. – DonaldRay

Antwort

14

Komplette Arbeits C# -Code für WPF-Anwendung, die zeigt, wie Deckel öffnen/schließen Ereignisse hören:

using System; 
using System.Diagnostics; 
using System.Runtime.InteropServices; 
using System.Windows; 
using System.Windows.Interop; 

namespace WpfApplication1 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     [DllImport(@"User32", SetLastError = true, EntryPoint = "RegisterPowerSettingNotification", 
      CallingConvention = CallingConvention.StdCall)] 

     private static extern IntPtr RegisterPowerSettingNotification(IntPtr hRecipient, ref Guid PowerSettingGuid, 
      Int32 Flags); 

     internal struct POWERBROADCAST_SETTING 
     { 
      public Guid PowerSetting; 
      public uint DataLength; 
      public byte Data; 
     } 

     Guid GUID_LIDSWITCH_STATE_CHANGE = new Guid(0xBA3E0F4D, 0xB817, 0x4094, 0xA2, 0xD1, 0xD5, 0x63, 0x79, 0xE6, 0xA0, 0xF3); 
     const int DEVICE_NOTIFY_WINDOW_HANDLE = 0x00000000; 
     const int WM_POWERBROADCAST = 0x0218; 
     const int PBT_POWERSETTINGCHANGE = 0x8013; 

     private bool? _previousLidState = null; 

     public MainWindow() 
     { 
      InitializeComponent(); 
      this.SourceInitialized += MainWindow_SourceInitialized; 
     } 

     void MainWindow_SourceInitialized(object sender, EventArgs e) 
     { 
      RegisterForPowerNotifications(); 
      IntPtr hwnd = new WindowInteropHelper(this).Handle; 
      HwndSource.FromHwnd(hwnd).AddHook(new HwndSourceHook(WndProc)); 
     } 

     private void RegisterForPowerNotifications() 
     { 
      IntPtr handle = new WindowInteropHelper(Application.Current.Windows[0]).Handle; 
      IntPtr hLIDSWITCHSTATECHANGE = RegisterPowerSettingNotification(handle, 
       ref GUID_LIDSWITCH_STATE_CHANGE, 
       DEVICE_NOTIFY_WINDOW_HANDLE); 
     } 

     IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) 
     { 
      switch (msg) 
      { 
       case WM_POWERBROADCAST: 
        OnPowerBroadcast(wParam, lParam); 
        break; 
       default: 
        break; 
      } 
      return IntPtr.Zero; 
     } 

     private void OnPowerBroadcast(IntPtr wParam, IntPtr lParam) 
     { 
      if ((int)wParam == PBT_POWERSETTINGCHANGE) 
      { 
       POWERBROADCAST_SETTING ps = (POWERBROADCAST_SETTING)Marshal.PtrToStructure(lParam, typeof(POWERBROADCAST_SETTING)); 
       IntPtr pData = (IntPtr)((int)lParam + Marshal.SizeOf(ps)); 
       Int32 iData = (Int32)Marshal.PtrToStructure(pData, typeof(Int32)); 
       if (ps.PowerSetting == GUID_LIDSWITCH_STATE_CHANGE) 
       { 
        bool isLidOpen = ps.Data != 0; 

        if (!isLidOpen == _previousLidState) 
        { 
         LidStatusChanged(isLidOpen); 
        } 

        _previousLidState = isLidOpen; 
       } 
      } 
     } 

     private void LidStatusChanged(bool isLidOpen) 
     { 
      if (isLidOpen) 
      { 
       //Do some action on lid open event 
       Debug.WriteLine("{0}: Lid opened!", DateTime.Now); 
      } 
      else 
      { 
       //Do some action on lid close event 
       Debug.WriteLine("{0}: Lid closed!", DateTime.Now); 
      } 
     } 
    } 
} 
+0

danke! woher hast du den Wert für GUID_LIDSWITCH_STATE_CHANGE erhalten? –

0

Power Managment

Umgang mit Energiespar-Events Der Fokus hat bisher schon auf die Erhaltung der Lebensdauer der Batterie, während die Anwendung ausgeführt wird. Es gibt eine zusätzliche Überlegung, die Sie machen sollten: wie sich Ihre Anwendung verhält, wenn der Computer den Vorgang aussetzt. Zwei Schlüsselszenarien sind hier zu berücksichtigen:

  • Wenn der Computer für einen bestimmten Zeitraum nicht benutzt wird, ist das aktive Energieschema wahrscheinlich angeben, dass die Hardware entweder geht in der Standby- Modus oder Ruhezustand.
  • Wenn der Benutzer eine Aktion ausführt, die den Computer in einen Suspend-Vorgang versetzt, z. B. Schließen des Deckels eines Laptops oder Drücken des Netzschalters.

Ich hoffe, es u irgendeine Richtung geben :)

+3

C'mon man, STRG + C, STRG + V, keine Einsicht? – bobobobo

+0

+1 für STRG + C, STRG + V –

+0

Sorry, Suspend ist in meinem Fall kein geeigneter Trigger. – Brad

8

Verwenden WM_POWERBROADCAST. Hier ist ein Link, der Ihnen helfen kann: Lid Close Action change notification

+0

Danke Zabba! Das ist genau das, wonach ich gesucht habe, aber es scheint, dass es nur für Vista und 7 funktioniert. Irgendwelche Gedanken da draußen für etwas Äquivalentes in XP? Danke noch einmal. – Brad

+0

Es funktioniert unter Windows 2000 und höher - http://msdn.microsoft.com/en-us/library/aa373247%28VS.85%29.aspx – Zabba

+2

Der Registrierungsschritt RegisterPowerSettingNotification erfordert Vista oder höher. –

5

Denken Sie daran, dass die meisten Laptops, wenn der Deckel schließt, drückt es einen Knopf. Dieser Knopf ist normalerweise nur ein Schlafknopf. Die WMI-Klassen geben das ACPI frei und Sie sollten idealerweise die PowerManagement-Klasse verwenden. Leider löst die Klasse kein Ereignis aus, wenn das Betriebssystem auf "nichts tun" gesetzt ist. Die einzige Möglichkeit wäre, mit dem DDK (Driver Development Kit) einen Filter zu erstellen, der das Ereignis IOCTL_GET_SYS_BUTTON_EVENT abfängt. Hier sind zwei Links, Ihnen zu helfen loszulegen:

http://blogs.msdn.com/b/doronh/archive/2006/09/08/746834.aspx

und

http://support.microsoft.com/kb/302092

+0

Danke, das ist hilfreich. – Brad

+0

@icemanind: Gibt es einen Einblick darüber, ob es möglich ist, einen vorgeschlagenen "Filter, der das IOCTL_GET_SYS_BUTTON_EVENT-Ereignis abfängt", von einem lokalen Dienst hinzuzufügen? – ahmd0

Verwandte Themen