深入淺出螢幕保護裝置程式編程
讀者對螢幕保護裝置程式已經相當熟悉了。去年泰坦尼克號的螢幕保護裝置程式風行了全世界,足見其魅力。有的螢幕保護裝置程式功能十分強大,可以提供圖象,動畫,音頻,視頻等所有的多媒體功能。儘管可以很容易獲得漂亮的螢幕保護裝置程式,但擁有自己的螢幕保護裝置程式對使用者也許更有吸引力。 VC5.0/6.0是開發螢幕保護裝置程式的好工具。靜態連結庫SCRNSAVE.LIB對螢幕保護裝置程式提供了支援。SCRNSAVE.LIB包含了建立螢幕保護裝置程式的主程式和預設功能,使用者可以方便地使用SDK進行編程並與之串連。儘管SDK編程相對MFC麻煩,但編寫相對簡單的螢幕保護裝置程式卻相當容易甚至比用MFC編程更簡單。 也可以使用MFC編寫螢幕保護裝置程式。但遺憾的是MFC不支援SCRNSAVE.LIB,必須手工完成原來由SCRNSAVE.LIB提供的功能,比較麻煩和不好理解。不過,編寫複雜的螢幕保護裝置程式時,MFC對於顯示模組和對話方塊處理可以提供比SDK方便得多的功能。為簡單起見先介紹如何使用SDK編寫螢幕保護裝置程式。
一. 螢幕保護裝置程式和SCRNSAVE.LIB 先從開發人員的角度對螢幕保護裝置程式說明如下: 首先,螢幕保護裝置程式是Win32 API 支援一種特殊的應用程式並由系統自動啟用。其機制是當條件滿足時,系統向當前使用中視窗發出字參數 wParam 值為SC_SCREENSAVE 的WM_SYSCOMMAND訊息,然後由當前使用中視窗執行SYSTEM.INI檔案中[boot]區指定的螢幕保護裝置程式。 螢幕保護裝置程式啟用的條件是 1. 在規定時間內沒有滑鼠或鍵盤輸入. 2. 當前的使用中視窗是標準的WINDOWS應用程式。因為非WINDOWS應用,不會理睬WM_SYSCOMMAND訊息。 3. 顯然,如果當前活動的程式接管了字參數 wParam 值為SC_SCREENSAVE 的WM_SYSCOMMAND 訊息並且不傳遞到 DefWindowProc函數就可以禁止螢幕保護裝置程式。這對某些運行中不願意被打斷的程式如視頻播放,光碟片燒錄程式特別有用。 其次,可以在控制台的顯示器中選擇需要的螢幕保護裝置程式,並可以配置螢幕保護裝置程式的參數。螢幕保護裝置程式應該提供配置螢幕保護裝置程式的對話方塊。 再次,螢幕保護裝置程式有特別的輸出函數,資源定義和變數聲明。SCRNSAVE.LIB包含了建立螢幕保護裝置程式的主程式。螢幕保護裝置程式啟動時SCRNSAVE.LIB自動建立一全屏視窗,並描述視窗類別為無游標的滿黑屏。 使用者編寫的螢幕保護裝置程式必須包含三個基本函數ScreenSaverProc,ScreenSaverConfigureDialog 和RegisterDialogClasses 並與SCRNSAVE.LIB串連。 1.ScreenSaverProc 視窗函數處理特定的訊息並把未處理的訊息傳遞給SCRNSAVE.LIB 。ScreenSaverProc 一般處理以下訊息: WM_CREATE 讀取.INI或註冊表的初始化資料,設定定時器以及其他初始化操作。 WM_ERASEBKGND 擦除背景為下一步繪圖作準備。 WM_TIMER 進行繪圖輸出。使用者可以實現自己的動畫功能以及其他動作。 WM_DESTROY 刪除定時器以及其他對象 ScreenSaverProc 把未處理的訊息傳遞到SCRNSAVE.LIB中的 DefScreenSaverProc函數 處理。由它完成許多複雜和關鍵的操作比如何時啟用,何時關閉等,大大方便了螢幕保護裝置程式的編寫。 2.ScreenSaverConfigureDialog函數處理螢幕保護裝置程式配置對話方塊。該對話方塊由控制台的顯示器設定程式調用。使用者輸入的配置資料輸出到.INI或註冊表中。 3. RegisterDialogClasses函數登記螢幕保護裝置程式配置對話方塊的視窗類別。如果不使用特殊的視窗或控制項,可以簡單地返回TRUE。 另外,編寫螢幕保護裝置程式還有一些原則。 1. 為使控制台能夠識別,螢幕保護裝置程式的副檔名必須改為.SCR並存放在WINDOWS目錄下。 2. 螢幕保護裝置程式的表徵圖(ICON)在資源檔中必須定義為ID_APP。ID_APP由系統的SCRNSAVE.H.定義。 3. 資源檔中必須包含一描述字串。該字串用於控制台顯示螢幕保護裝置程式的名字。它必須位於字串表的首位。SCRNSAVE.H.定義其ID為1。 4. 資源檔中螢幕保護裝置程式配置對話方塊的ID必須為DLG_SCRNSAVECONFIGURE。它由系統的SCRNSAVE.H.定義。
二.編程執行個體 1.最小的螢幕保護裝置程式MiniSaver。這是一個僅包含最基本模組的螢幕保護裝置程式,運行時在螢幕上顯示一行活動的文字。步驟如下: 第一步,在VC5.0/6.0中建立32位應用工程(不選MFC WIZARD EXE).建立如下的MiniSaver.CPP檔案: #include #include // SCRNSAVE.LIB的標頭檔 #include "resource.h" //聲明三個基本的函數 LRESULT WINAPI ScreenSaveProc (HWND,UINT,WPARAM,LPARAM); BOOL WINAPI ScreenSaveConfigureDialog (HWND,UINT,WPARAM,LPARAM); BOOL WINAPI RegisterDialogClasses(HINSTANCE); //定義三個基本的函數 LRESULT WINAPI ScreenSaverProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { HDC hDC; RECT rc; static int xpos;//文本的橫座標 static char SlideText[]="歡迎使用螢幕保護裝置程式!"; static UINT timerID;//定時器 switch (message) { case WM_CREATE: xpos=0; timerID=SetTimer(hWnd,1,250,NULL);//設定定時器 break; case WM_ERASEBKGND: //空操作,交由DefScreenSaverProc處理 break; case WM_TIMER: hDC=GetDC(hWnd); //清屏 SetRect(&rc,0,0,GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)) FillRect(hDC,&rc,GetStockObject(BLACK_BRUSH)); //輸出文本 SetTextColor(hDC,RGB(255*rand(), 255*rand(),255*rand())); SetBkColor(hDC,RGB(0,0,0)); TextOut(hDC,xpos,GetSystemMetrics(SM_CYSCREEN)/2, SlideText,strlen(SlideText)); //移動文本的橫座標 xpos=(xpos+10)%GetSystemMetrics(SM_CXSCREEN); ReleaseDC(hWnd,hDC); break; case WM_DESTROY: KillTimer(hWnd,timerID);//刪除定時器 PostQuitMessage (0); return 0; } return DefScreenSaverProc (hWnd,message,wParam,lParam); } BOOL WINAPI ScreenSaverConfigureDialog (HWND hWnd,UINT message,WPARAM wParam, LPARAM lParam) {//暫時不需要配置對話方塊,僅返回FALSE return FALSE; } BOOL WINAPI RegisterDialogClasses (HINSTANCE hInstance) {//一般不需要,僅返回TRUE return TRUE; } 第二步,定義資源檔MiniSaver.rc。在VC環境下產生一表徵圖,其ID為ID_APP。向字串表加入ID為IDS_DESCRIPTION字串"MiniSaver",並作為字串表第一項 第三步,編譯串連並將產生的MiniSaver.EXE更名為MiniSaver.SCR拷入WINDOWS目錄。注意, 編譯前一定要在Project菜單的Setting中的Link選項中加上SCRNSAVE.LIB庫。 第四步,控制台的顯示器設定中選擇螢幕保護裝置程式MiniSaver就可以使用了。注意不要急於配置螢幕保護裝置程式,因為MiniSaver還有沒提供配置對話方塊。
2.較完整的螢幕保護裝置程式MySaver。該螢幕保護裝置程式提供了配置對話方塊和關於對話方塊,並且使用了圖象顯示。讀者可以將自己喜愛的圖象加到資源中。 第一步,在VC5.0/6.0中建立32位應用工程(不選MFC WIZARD EXE)並定義資源檔MiniSaver.rc。 在VC環境下產生一表徵圖,其ID為ID_APP。 向字串表加入ID為IDS_DESCRIPTION字串"MiniSaver",並作為字串表第一項。加入ID為idsAPPName 字串"Screen Saver.MySaver",說明見後面程式。 加入ID為IDB_BITMAP1的位元影像 加入ID為DLG_ABOUT對話方塊。僅有一ID為IDOK的按鈕 加入ID為ID_APP。此對話的ID由SCRNSAVE.H定義且只能為DLG_SCRNSAVECONFIGURE。其中有ID為IDC_EDIT 的EDIT控制項,ID為IDOK,IDCANCEL和IDABOUT的按鈕。 值得注意的是RESOURCE.H定義的ID_APP和DLG_SCRNSAVECONFIGURE可能與SCRNSAVE.H預定義的值衝突,可 手動地將RESOURCE.H中的ID_APP設為100,DLG_SCRNSAVECONFIGURE設為2003即可。 第二步,建立如下的MySaver.CPP檔案: #include #include #include "resource.h" //聲明三個基本的函數 LRESULT WINAPI ScreenSaveProc (HWND,UINT,WPARAM,LPARAM); BOOL WINAPI ScreenSaveConfigureDialog (HWND,UINT,WPARAM,LPARAM); BOOL WINAPI RegisterDialogClasses(HINSTANCE); BOOL WINAPI AboutDialog(HWND,UINT,WPARAM,LPARAM); //定義全域變數 char szIniFileName[]="control.ini"; //螢幕保護裝置程式配置資料存放在control.ini檔案 char szSection[32]; //螢幕保護裝置程式配置資料在control.ini檔案位置區名稱 char szEntry[]="Slide Text:"; //螢幕保護裝置程式配置資料項目名稱 char SlideText[256]; //螢幕保護裝置程式配置資料,這裡是常值內容 //定義三個基本的函數 LRESULT WINAPI ScreenSaverProc (HWND hWnd,UINT message, WPARAM wParam, LPARAM lParam) { static HBITMAP hBmp;//位元影像控制代碼 HDC hDC,hMemDC;//hMemDC是記憶體裝置,緩衝位元影像。 RECT rc; static int xpos=0; static UINT timerID; switch (message) { case WM_CREATE: //檔案位置區名稱szSection賦值為資源 idsAPPName。其中hMainInstance為//SCRNSAVE.LIB 定義的螢幕保護裝置程式執行個體控制代碼 LoadString(hMainInstance,idsAPPName, szSection,sizeof(szSection)); strcpy(SlideText,"歡迎使用螢幕保護裝置程式!"); //讀control.ini檔案中[Screen Saver.MySaver] 區的配置資料到SlideText GetPrivateProfileString(szSection,szEntry, SlideText,SlideText, sizeof(SlideText),szIniFileName); //取位元影像 hBmp=LoadBitmap(hMainInstance, MAKEINTRESOURCE(IDB_BITMAP1)); timerID=SetTimer(hWnd,1,250,NULL); break; case WM_ERASEBKGND: hDC=GetDC(hWnd); //顯示位元影像 hMemDC=CreateCompatibleDC(hDC); SelectObject(hMemDC,hBmp); SetRect(&rc,0,0,GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)-25); BitBlt(hDC,rc.top,rc.left,rc.right,rc.bottom, hMemDC,rc.top,rc.left,SRCCOPY); //清除底行,為文本顯示作準備。 SetRect(&rc,0,GetSystemMetrics(SM_CYSCREEN)-25 GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); FillRect(hDC,&rc,GetStockObject(BLACK_BRUSH)); ReleaseDC(hWnd,hDC); DeleteDC(hMemDC); return 1; case WM_TIMER: hDC=GetDC(hWnd); //清除底行 SetRect(&rc,0,GetSystemMetrics(SM_CYSCREEN)-25, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); FillRect(hDC,&rc,GetStockObject(BLACK_BRUSH)); //輸出文本 SetTextColor(hDC,RGB(255*rand(), 255*rand(),255*rand())); SetBkColor(hDC,RGB(0,0,0)); TextOut(hDC,xpos,GetSystemMetrics(SM_CYSCREEN)-25, SlideText,strlen(SlideText)); xpos=(xpos+10)%GetSystemMetrics(SM_CXSCREEN); ReleaseDC(hWnd,hDC); break; case WM_DESTROY: DeleteObject(hBmp); KillTimer(hWnd,timerID); PostQuitMessage (0); return 0; } return DefScreenSaverProc (hWnd,message,wParam,lParam); } BOOL WINAPI ScreenSaverConfigureDialog (HWND hWnd,UINT message,WPARAM wParam, LPARAM lParam) { switch (message) { case WM_INITDIALOG: LoadString(hMainInstance,idsAPPName, szSection,sizeof(szSection)); strcpy(SlideText,"歡迎使用螢幕保護裝置程式!"); GetPrivateProfileString(szSection, szEntry,SlideText, SlideText,sizeof(SlideText),szIniFileName); SetDlgItemText(hWnd,IDC_EDIT,SlideText); SetFocus(GetDlgItem(hWnd,IDC_EDIT)); return FALSE; case WM_COMMAND: switch(wParam) { case IDOK: //取EDIT控制項文本資料並寫入control.ini檔案 GetDlgItemText(hWnd,IDC_EDIT, SlideText,sizeof(SlideText)); WritePrivateProfileString(szSection, szEntry,SlideText,szIniFileName); EndDialog(hWnd,TRUE); return TRUE; case IDCANCEL: EndDialog(hWnd,FALSE); return TRUE; case IDABOUT: //調用ABOUT對話方塊 DialogBox(hMainInstance, MAKEINTRESOURCE(DLG_ABOUT), hWnd,(FARPROC)AboutDialog); return TRUE; } break; } return FALSE; } BOOL WINAPI RegisterDialogClasses (HINSTANCE hInstance) { return TRUE; } BOOL WINAPI AboutDialog (HWND hWnd,UINT message,WPARAM wParam, LPARAM lParam) { switch (message) { case WM_INITDIALOG: return TRUE; case WM_COMMAND: switch(wParam) { case IDOK: EndDialog(hWnd,TRUE); return TRUE; } break; } return FALSE; } 最後,編譯串連並將產生的MiniSaver.EXE更名為MiniSaver.SCR拷入WINDOWS目錄。此時可以使用配置對話方塊了。 作者會員名:heliking
|
|