本文主要介紹屏幕保護程序的一些相關知識,以及其在安全方面的用途,同時介紹了如何使用 .NET 開發一款屏幕保護程序,并對核心功能做了介紹,案例代碼開源:https://github.com/sangyuxiaowu/HackerScreenSaver
背景
前幾天在論壇看到想保護公司的服務器共享文件的安全,但是員工自己的電腦總是忘記關閉關機,想再設置一個密碼。可是這樣不應該先解決一下員工電腦總是忘記關的問題么?
如果你要離開設備幾分鐘,最好將其鎖定,以免他人看到屏幕上的內容,或訪問設備上的任何內容。按 Windows 徽標鍵 + L 立即將其鎖定。
動態鎖
當然,也可以通過動態鎖的方式實現,Windows 可以使用與你的電腦配對的設備檢測你何時離開,并在你的已配對設備超出藍牙范圍后立即鎖定你的電腦。這使得當你離開電腦并且忘記將其鎖定時,其他人更難于訪問你的設備。配對完成后,只需在離開時隨身帶上手機,你的電腦便可在你超出藍牙覆蓋范圍之后大約一分鐘自動鎖定。

但是主動鎖定和動態鎖,一個要主動一個要配置和藍牙配合都有一些不足,如何更方便的實現?
屏幕保護程序
屏幕保護程序在我印象里好像是 Windows XP 的時代,現在好像沒見過幾個 Win10 和 Win11 用戶去專門的設置這個,倒是看過 Win7 的用戶在用。
針對上門提出的超時鎖定,這個屏幕保護程序可以大有作為,我們可以勾選“在恢復時顯示登錄屏幕”,這樣我們在不使用電腦第一段時間后就需要輸入密碼了。
轉到"設置>個性化>鎖屏界面,然后選擇"屏幕保護程序設置"。

屏幕保護程序有用嗎
電腦里的屏幕保護程序對保護屏幕有用嗎?作為一個古老的功能,實際上屏幕保護程序僅對使用圖形界面操作系統的 CRT 顯示器有保護作用。對于CRT來說,屏幕保護是為了不讓屏幕一直保持靜態的畫面太長時間。
因為不同顯示器的工作原理不同,比如筆記本常用的 LCD, 一直開著屏幕保護反而是幫了倒忙,所以無論什么顯示器如果是長時間不用電腦而又需要主機處于運行狀態的話,把顯示器關掉才是明智的做法。
這里我們可以同時配合“屏幕超時設置”,在一定時間下關閉電腦屏幕。比如1分鐘進屏幕保護,3分鐘直接關閉屏幕。

設計一個屏幕保護程序
在設計之前我們需要了解一些基本的常識。
屏幕保護程序命令行參數
屏幕保護程序的開發需要提供一些啟動參數供設置和預覽。Windows 通過命令行參數與屏幕保存程序通信。具體可查閱文檔:屏幕保護程序命令行參數[1]
參數 | 說明 |
空 | 顯示設置對話框 |
/c | 顯示設置對話框,使用模態對話框顯示到前臺 |
/p <HWND> | 在<HWND>窗體下預覽效果 |
/s | 啟動屏幕保護程序 |
/S | 右鍵scr的Test啟動 |
了解了啟動參數,我們需要對軟件的參數啟動進行處理。
/// <summary>
/// 應用程序的主入口點。
/// </summary>
[STAThread]
static void Main(string[] args)
{Application.EnableVisualStyles();Application.SetCompatibleTextRenderingDefault(false);if (args.Length > 0){switch (args[0].ToLower().Trim().Substring(0, 2)){case "/p":Main pri = new Main(new IntPtr(long.Parse(args[1])));pri.ShowDialog();break;case "/s"://Test 或 執行屏保,大寫為測試,小寫為被啟動,這里不做區分Application.Run(new Main());break;default:ShowSetting();break;}}else{ShowSetting();}
}static void ShowSetting()
{MessageBox.Show("這個屏幕保護程序沒有可以設置的選項。","黑客模擬器",MessageBoxButtons.OK,MessageBoxIcon.Information);Application.Exit();
}
效果實現思路
我們常常會在一些影視作品中里看到一些黑客高手,在電腦前一陣噼里啪啦“黑”進別人的安全系統的場景。
GeekTyper[2]?就是國外網友制作的幾個用來裝 X 的娛樂網頁。

所以軟件的主要實現是放置一個無框的窗體,通過 WebBrowser 來顯示黑客效果的網頁。我們只需要在軟件啟動時用 WebBrowser 加載喜歡的效果的網頁就可以了。
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.TopMost = true;
this.WindowState = System.Windows.Forms.FormWindowState.Maximized;
這里我們可以自行指定一個 URI ,但是為了離線使用,可以將其放到本地,這里我打包了一個分享在倉庫的?releases
。
//webB.Url = new Uri("https://geektyper.com/SCP");
webB.Navigate(Application.StartupPath + "\\html\\hacker.html");
注意退出
編碼測試時還有一個特別需要注意的事情,一定要寫好退出功能。如果沒寫好就安裝屏保測試的話,就不好退出了呀, Ctrl+Alt+Del 試試吧。
這里說的退出是指屏保運行后,用戶操作了鼠標或者是鍵盤就需要退出屏保程序。因為這里用了 WebBrowser ,同時我們需要考慮多顯示器的情況,所以鼠標鍵盤的事件需要監聽全局,這里使用的是?MouseKeyHook[3]?庫。
public Main()
{InitializeComponent();// 鼠標鍵盤事件用于結束屏保m_GlobalHook = Hook.GlobalEvents();m_GlobalHook.MouseClick += M_GlobalHook_MouseClick;m_GlobalHook.KeyPress += M_GlobalHook_KeyPress;m_GlobalHook.MouseMove += M_GlobalHook_MouseMove;
}
private void M_GlobalHook_KeyPress(object sender, KeyPressEventArgs e)
{Application.Exit();
}private void M_GlobalHook_MouseClick(object sender, MouseEventArgs e)
{Application.Exit();
}private bool isActive = false;
private Point mouseLocation;
/// <summary>
/// 鼠標動了一定程度,就結束屏保
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void M_GlobalHook_MouseMove(object sender, MouseEventArgs e)
{if (isPreviewMode) return;if (!isActive){isActive = true;mouseLocation = new Point(e.X, e.Y);return;}if ((Math.Abs(e.X - mouseLocation.X) > 10) ||(Math.Abs(e.Y - mouseLocation.Y) > 10)){Application.Exit();}
}
窗體預覽的處理
前面的窗體預覽我們處理好了啟動參數,只需要通過 WinAPI 更改父窗體就行,但是因為只是簡單的處理,沒有做縮放,所以我就簡單的放了個圖片替代了。
[DllImport("user32.dll")]
private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
public Main(IntPtr intPtr)
{InitializeComponent();//預覽SetParent(this.Handle, intPtr);isPreviewMode = true;picLogo.Visible = true;
}
安裝測試
編輯好代碼,我們生成 exe 程序后,只需要將其后綴名改為 scr 即可作為屏幕保護程序使用,這時右鍵菜單就可以看到測試,配置和安裝。

最后
至此,我們已經完成了一個屏幕保護程序的開發,快去秀給自己的女朋友吧!當然除了秀技術,你的網頁可以換成類似下面的這種。

以上代碼分享在 https://github.com/sangyuxiaowu/HackerScreenSaver 感興趣的同學看一眼,順便求個 Star,感謝。
References
[1]
?屏幕保護程序命令行參數:?https://learn.microsoft.com/zh-cn/troubleshoot/windows/win32/screen-saver-command-line[2]
?GeekTyper:?https://geektyper.com/[3]
?MouseKeyHook:?https://www.nuget.org/packages/MouseKeyHook/