2010-02-05 25 views
12

Xin chào, tôi đã tìm kiếm nhưng tôi không thể tìm thấy câu trả lời. Làm thế nào để tôi biết khi nào màn hình tắt hoặc bật. Không phải là SystemEvents.PowerModeChanged. Tôi không biết làm thế nào để lấy SỰ KIỆN màn hình/màn hìnhC# Làm thế nào để có được các sự kiện khi màn hình/màn hình chuyển sang TẮT nguồn hoặc BẬT?

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

Có lẽ tôi có thể giải thích tăng thêm của tôi, do đó có lẽ là một giải pháp tốt hơn. Tôi có một dịch vụ WCF ràng buộc kép đang chạy. Nó đang chạy trên một archos (máy tính bảng di động). Tôi muốn rằng khi người dùng ngừng làm việc cho một thời gian nhàn rỗi, kết nối đóng cửa ngay lập tức, và khi máy tính trở về từ nhàn rỗi, anh ta kết nối lại ngay lập tức. Ý tưởng của Application Idle on Code project từ Tom đã là một ý tưởng hay. Tiêu thụ điện ít hơn, càng tốt. Khởi động phải nhanh nhất có thể.

Trả lời

7

Hãy xem blog này here sẽ giúp bạn thực hiện những gì bạn đang cố gắng đạt được. Ngoài ra bạn cần phải thực hiện một sự kiện tùy chỉnh để làm điều này cho bạn một cái gì đó như thế này:

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: Như Manu là không chắc chắn làm thế nào để lấy lại các sự kiện, chỉnh sửa này sẽ bao gồm một mẫu code về cách sử dụng lớp này như hình dưới đây.

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

    } 
} 

Sau khi xem xét mã này, và nhận ra rằng có điều gì đó không hoàn toàn đúng, nó chợt nhận ra tôi rằng Manu đang tìm kiếm một cách để thẩm vấn hệ thống để phát hiện tình trạng điện Monitor mà không phải là có sẵn, nhưng, mã cho thấy rằng lập trình, màn hình có thể được bật/tắt/chế độ chờ, đồng thời kích hoạt một sự kiện, nhưng anh ta muốn nó có thể móc trong WndProc của một biểu mẫu và xử lý thông báo cho biết trạng thái của Giám sát ... bây giờ, tại thời điểm này, tôi sẽ bày tỏ ý kiến ​​của tôi về điều này.

Tôi không chắc chắn 100% nếu điều này có thể được thực hiện hay không Windows thực sự gửi một thông điệp phát sóng nói điều gì đó như 'Hey! Màn hình sẽ ngủ "hoặc" Hey! Màn hình đang bật nguồn ', tôi sợ phải nói, Màn hình không thực sự gửi tín hiệu phần mềm nào đó đến Windows để thông báo rằng nó sẽ chuyển sang chế độ ngủ/tắt/bật. Bây giờ nếu có ai có đề xuất, gợi ý, manh mối về điều đó, vui lòng đăng bình luận của bạn ...

Phần mềm Energy Star như một phần của tab ScreenSaver được tìm thấy khi bạn nhấp chuột phải vào màn hình bất kỳ ở đâu, một cửa sổ pop -up menu xuất hiện, nhấp chuột trái vào 'Properties', hộp thoại 'Display' xuất hiện, với các trang tab khác nhau, nhấp chuột trái vào 'ScreenSaver', Nhấp vào nút 'Power' như một phần của hộp nhóm 'Monitor Power', đó là một phần của hộp thoại, bằng cách nào đó kích hoạt hệ thống phụ Windows (card đồ họa?/Trình điều khiển Energy Star?) để gửi tín hiệu phần cứng để bật chức năng tiết kiệm năng lượng của Màn hình ... (Màn hình mới không có điều này được bật theo mặc định AFAIK ... vui lòng loại bỏ khái niệm này ...)

Trừ khi có tài liệu không có giấy tờ d API ở đâu đó được nhúng và chôn sâu bên trong trình điều khiển phần mềm Energy-Power (một API chắc chắn thực sự được kích hoạt như cách nhấn vào nút 'Power' gửi tín hiệu đó đến Monitor trong đó chế độ Power thực sự được kích hoạt như là kết quả!) có lẽ, bằng cách chạy một luồng trong nền của ứng dụng biểu mẫu đã nói, bỏ phiếu để thẩm vấn chưa, chức năng chưa biết hoặc API để kiểm tra trạng thái nguồn - phải có thứ gì đó mà chỉ có Microsoft mới biết ... sau khi tất cả, Energy Star cho thấy Microsoft làm thế nào để kích hoạt chế độ tiết kiệm năng lượng trên màn hình chính nó, chắc chắn nó không phải là một con đường một chiều? hoặc là nó?

Xin lỗi Manu nếu tôi không thể giúp đỡ hơn nữa .... :(

Chỉnh sửa # 2: Tôi nghĩ về những gì tôi đã viết trước đó trong soạn thảo và đã làm một chút đào bới xung quanh ủng hộ cho một câu trả lời và Tôi nghĩ rằng tôi đã đưa ra câu trả lời, nhưng trước tiên, một ý nghĩ xuất hiện trong đầu tôi, xem tài liệu này here - một tài liệu pdf từ 'terranovum.com', đầu mối (hoặc vì vậy tôi nghĩ ...) nằm trong sổ đăng ký, bằng cách sử dụng hai khóa đăng ký cuối cùng trên trang cuối cùng của tài liệu chứa khoảng trống được chỉ định vào số giây và kết hợp với bài viết CodeProject này để tìm thời gian rảnh, sẽ dễ dàng xác định khi màn hình chuyển sang chế độ chờ , nghe có vẻ đơn giản hay tôi nghĩ, Manu cũng không muốn khái niệm đó ...

Điều tra thêm với google dẫn tôi đến kết luận này, câu trả lời nằm trong phần mở rộng của đặc điểm VESA BIOSDPMS (Hiển thị báo hiệu quản lý nguồn), bây giờ là câu hỏi phát sinh từ điều này , là cách bạn thẩm vấn tín hiệu trên bios VESA, bây giờ, rất nhiều card đồ họa hiện đại có VESA Bios gắn vào nó, vì vậy phải có cổng phần cứng ở đâu đó bạn có thể đọc giá trị của các chân, sử dụng tuyến đường này sẽ yêu cầu sử dụng InpOut32 hoặc nếu bạn có Windows 64 bit, có một InpOut64 qua pinvoke. Về cơ bản nếu bạn có thể nhớ lại bằng cách sử dụng Turbo C hoặc Turbo Pascal, (cả 16bit cho DOS) có một thường trình gọi là inport/outport hoặc tương tự như đọc cổng phần cứng, hoặc thậm chí GWBASIC sử dụng peek/poke. Nếu có thể tìm thấy địa chỉ của cổng phần cứng, thì các giá trị có thể được thẩm vấn để xác định xem Màn hình có ở chế độ chờ/tắt nguồn/tạm dừng/bật hay không bằng cách kiểm tra Đồng bộ ngang và Đồng bộ dọc, điều này tôi nghĩ là giải pháp đáng tin cậy hơn. ..

Xin lỗi cho câu trả lời dài nhưng cảm thấy mình phải viết ra những suy nghĩ của tôi ....

vẫn còn hy vọng có Manu :);)

+1

Không thực sự, làm thế nào để bạn lấy các sự kiện. Làm thế nào để biết nếu nó BẬT nguồn hoặc TẮT nguồn? - Sau 10 phút màn hình của tôi bị mờ. - Sau 15 phút màn hình của tôi tắt. - Tôi di chuyển chuột, màn hình sẽ BẬT. Cách nhận sự kiện này? (không phải là sự kiện phiên) – Manu

+0

@Manu: Hãy để tôi chỉnh sửa câu trả lời này để bao gồm một mẫu làm thế nào để lấy các sự kiện .... – t0mm13b

+0

Wow, interestin. Tôi không nghĩ Gonne quá phức tạp. Tôi không phải là một chuyên gia, chắc chắn không phải với registry. Vì vậy, tôi hơi sợ khi chạm vào đó. "Ứng dụng nhàn rỗi" đã là một ý tưởng hay. – 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

Vui lòng thêm một số nhận xét trên mã của bạn (tại sao mã này giải quyết vấn đề được đặt ra). Nếu không có một lời giải thích, đây không phải là một câu trả lời. – Artemix

3

phần thiếu là tôi đã không đăng ký cho các sự kiện.

Tìm thấy rằng có một ví dụ quản lý điện năng từ 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

Liên kết bạn cung cấp bị hỏng ngay bây giờ và mã mẫu của bạn thiếu các giá trị cho dòng đầu tiên. Vì vậy, chỉ dành cho bất kỳ ai khác có thể gặp phải điều này trong tương lai: cho giá trị GUID_MONITOR_POWER_ON (02731015-4510-4526-99e6-e5a17ebd1aea) Tôi đã sử dụng [liên kết này] (https://msdn.microsoft.com/en-us/ thư viện/windows/desktop/hh448380 (v = vs.85) .aspx) làm tham chiếu và 0 cho giá trị DEVICE_NOTIFY_WINDOW_HANDLE. –

Các vấn đề liên quan