下載原始碼:ScreenSaver.rar
初學C#的時候就曾想過寫螢幕保護裝置,當時覺得很深奧,摸不著頭緒,就放棄了。今日又重新拾起,突然覺得也就是那麼一回事,知道了就很簡單了。好的,下面就介紹一下如何利用C#製作螢幕保護裝置。
開啟Visual Studio.net2005(其他版本也差不多),建立一個windows項目。這次的屏保是模仿Windows XP內建的一個螢幕保護裝置。
把視窗的屬性設定一下:
1.首先把 WindowState 設定為 FormWindowState.Maximized 這樣視窗就可以在開啟之後呈現最大化的狀態。
2.把TopMost 設定為true,這樣使得視窗處於最頂層,就是所謂的“永遠在前”,相信用過千千靜聽,金山詞霸等軟體的朋友應該熟悉。
3.把FormBorderStyle 設定為FormBorderStyle.None ,這樣視窗就沒有邊框,即沒有了標題列,周圍的一圈邊框。也就省去了一個個去掉MaximizeBox ,MinimizeBox了。
4.把BackColor設定為Color.Black, 這樣視窗背景色就變成黑色了
5.ShowInTaskBar 設定為false,(這個步驟可以省去,本身最大化就看不到工作列了)
其他的屬性修改都是多餘了,當然把name等等類似改改也行,總之,上面5個(嚴格的說4個)弄好了,UI方面就設計完畢了。
下面拖動一個timer控制項進來,將其Enabled屬性設定為true,Interval設定為10000(因為以milliseconds為單位,所以這裡設定為10,000,也就是10s)。
加timer控制項是為了每隔一定的事件觸發一個事件。因此給timer加一個事件,點擊Solution Explorer 上面的閃電表徵圖,添加唯一的一個Tick事件。
下面就開始設計演算法了,其實也是再簡單不過了,隨機產生一個點,然後再該處繪製預先準備好的圖片。(如果為了好看點,可以設定座標之間的關係)
private readonly int screenWidth;
private readonly int screenHeight;
private Bitmap bitmap = new Bitmap("ms.bmp");
private Random random = new Random();
private int x = 0;
private int y = 0;
增加若干成員變數, 挺有self-documenting的味道,我就不過多解釋了,前兩個是標誌螢幕的寬度和高度,
然後是一個位元影像對象,儲存預先準備的圖片,這裡是一張bitmap。random是一個隨即類對象,用來產生隨機點的。再下面分別是產生的隨機點的x,y座標。
建構函式內添加
Rectangle rect = Screen.PrimaryScreen.Bounds;
screenWidth = rect.Width;
screenHeight = rect.Height;
第一句話是用來獲得整個顯示器的邊界範圍。然後分別把寬度和高度賦值給成員變數。
註:Screen類提供了一些與顯示器相關的屬性,感興趣的朋友可以參閱MSDN
下面填補Tick事件
private void timer1_Tick(object sender, EventArgs e)
{
x = random.Next(screenWidth);
y = random.Next(screenHeight);
if (x + bitmap.Width > screenWidth)
{
x = screenWidth - bitmap.Width;
}
if (y + bitmap.Height > screenHeight)
{
y = screenHeight - bitmap.Height;
}
this.Invalidate();
}
上面是擷取一個x,y座標分別不大於顯示器的寬度和高度的點。為了美觀一點,判斷圖片是否超過螢幕邊界,對x,y進行了一些處理, 不是很難,相信大家都能看懂。最後重新整理螢幕,調用paint事件。
我想您一定知道了,對, 在Form的paint事件裡面有了一句畫圖的語句,回答正確!
e.Graphics.DrawImage(bitmap, x, y, bitmap.Width,bitmap.Height);
註: 我在編寫程式測試的過程中,發現了一個非常細微也很重要的地方。也正是因為它,才引起了我寫這篇文章的慾望。 要指出的是: Graphics類下面有一系列的DrawImage重載函數。
特別關注這兩個(我僅僅來出來舉例,其他相應的大家自會明白)
public void DrawImage( Image image, Point point);
和
public void DrawImage(Image image,int x,int y,int width,int height);
前者是在指定點繪製物理大小的圖片,而後者是在指定點繪製指定縮放大小的圖片。
兩者有什麼不同呢? 給大家看一段話應該就懂了!
Image Object Storage Service像素寬度值及水平解析度值(DPI)。映像的物理寬度(以英寸為單位)等於像素寬度除以水平解析度。例如,像素寬度為 216、水平解析度為 72 點/英寸的映像的物理寬度為 3 英寸。此說明同樣適用於像素高度和物理高度。
此方法使用映像的物理大小繪製映像,因此無論顯示裝置的解析度(DPI)是多少,映像大小(以英寸為單位)都是正確的。例如,假定映像的像素寬度為 216,水平解析度為 72 點/英寸。如果調用此方法在解析度為 96 點/英寸的裝置上繪製該映像,則所呈現映像的像素寬度是 (216/72)*96 = 288。
哈哈, 也就是說前者再用圖片的物理大小,後者使用指定大小。物理大小在不同的水平解析度的顯示器上顯示的始終是圖片的真實大小。(注意,bitmap 的width和height返回的大小都是以 pixel(像素)為單位的)。疑雲頓時解開了!
最後添加一個程式退出的操作,這裡我使用的是鍵盤按下或者滑鼠焦點變換。
這個不難,略過。
到此為止,把程式執行一下就可以看到預期的效果了。最後把bin/debug或者
bin/release下的可執行程式尾碼改成scr,並拷貝到系統硬碟Windows的system32下(圖片也拷貝進去哦!)
這樣通過案頭屬性的螢幕保護裝置程式設定一下就可以投入使用了,是不是很炫呢!趕緊試試吧!
程式在 Windows XP SP2 + Visual Studio.net 2005 下編譯通過。
後記:
1.筆者發現,在Visual Studio.net2005下面建C#項目的時候有一項就是。是在屏保裡面顯示Rss內容的。待我研究一陣子再向大家彙報吧。
2.關於圖片,拷貝到system32下委實不方便,我們可以使用內嵌資源編譯進exe檔案裡面。