C# 息屏操作出現閃屏

windows大屏使用場景,關閉顯示器是一個常用操作。

操作系統提供了相應的API,應用層調用:

 1     //廣播消息,所有頂級窗體都會接收
 2     private static readonly IntPtr HWND_BROADCAST = new IntPtr(0xffff);
 3     //系統消息
 4     private const uint WM_SYSCOMMAND = 0x112;
 5     //關閉顯示器的系統命令
 6     private const int SC_MONITORPOWER = 0xF170;
 7     //2爲PowerOff, 1爲省電狀態,-1爲開機
 8     private const int MonitorPowerOff = 2; 
 9     // 定義Win32 API中的SendMessage函數
10     [DllImport("user32.dll",CharSet = CharSet.Auto)]
11     private static extern IntPtr SendMessage(IntPtr hWnd, uint hMsg, int wParam, int lParam);
12     private void SendMessage_OnClick(object sender, RoutedEventArgs e)
13     {
14         SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, MonitorPowerOff);
15     }

以上是息屏的實現。但經測試驗證,上面方案有較大概率導致整機時序信號反覆拉高拉低、出現長時間的閃屏。

經過反覆嘗試,發現是API調用錯了。

原因應該是,在對所有窗口廣播息屏,這需要更長時間完成這個操作。這時點擊屏幕去觸發亮屏,系統的操作被打亂導致時序紊亂,現象就是屏會閃來閃去。

爲了驗證,我調用廣播息屏後,等待一段時間再去點擊屏幕,則不會出現閃屏。

所以,測試反饋問題是概率性事件,就是測試手法導致的。打開窗口少的情況下,息屏後手慢點可能就復現不了。

息屏操作不廣播,只需要通知當前應用窗口。以下是正確調用姿勢:

1     private void SendMessage_OnClick(object sender, RoutedEventArgs e)
2     {
3         var interopHelper = new WindowInteropHelper(this);
4         SendMessage(interopHelper.Handle, WM_SYSCOMMAND, SC_MONITORPOWER, MonitorPowerOff);
5     }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章