用VC++6.0 编写一个完整的
生活随笔
收集整理的這篇文章主要介紹了
用VC++6.0 编写一个完整的
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
屏幕保護程序是一個Win32應用程序,與一般的Win32應用程序不同之處在于:1、擴展名要求為 SCR ;2、命令行要有一定的格式,以便操作系統向其傳遞信息,如 運行模式,父窗口句柄(Handle to Parent Window)等 ;3、其他一些消息相應方面的要求。本文將首先介紹屏幕保護程序的命令行格式及實現的方法,然后介紹各個相應函數,并通過Window主函數WinMin()勾畫出屏幕保護程序的主框架,最后介紹編譯步驟和注意事項
屏幕保護程序的命令行格式 :文件名 / [運行模式] /[窗口句柄]。
其中運行模式有五種選擇:
1.??? “運行模式”= ‘c’ 或 ‘C ’, 句柄為一串數字, 或文件名后沒有任何參數。
屏保程序設置方式,Window 顯示屬性_屏幕保護程序_設置按鈕調用,數字為調用函數的窗口句柄(Handle to Parent Window)(十進制),如果沒有數字,句柄為NULL。
2.??? “運行模式”=‘t’或‘T’。
測試方式,忽略句柄數字。 3.??? “運行模式”=‘p’或‘P’。
預覽方式,Window 顯示屬性_屏幕保護程序_預覽按鈕調用,句柄為調用函數的窗口句柄。 4.??? “運行模式”=‘a’或‘A’。
密碼設置方式, Window 顯示屬性_屏幕保護程序_密碼保護_更改按鈕調用。句柄為調用函數的Window 句柄。 5.??? 其它(通常“運行模式”=‘s’)
屏幕保護程序正常運行模式。 因此,編寫屏幕保護程序的首要任務是過濾命令行,提取對應的系統調用方式和其他信息,本文用自定義函數ParseCommandline( )實現: //用enum定義五種調用方式: enum SaverMode { ??????????????????????????????????? sm_config, ??????????????????????????????????? sm_preview, ??????????????????????????????????? sm_full, ??????????????????????????????????? sm_test, ??????????????????????????????????? sm_passwordchange }; ? //命令行過濾函數,命令行獲得函數是用API ?GetCommandLine( )。 SaverMode ParseCommandLine( TCHAR* pstrCommandLine ) { ????? g_hWndParent = NULL; //全局變量(global varibale) 在頭函數或主文件開始處定義。 ????? // 跳過長文件名中的路徑和空格。 ????? if (*pstrCommandLine == TEXT('/"')) ?????? { ???????? pstrCommandLine++; ???????? while (*pstrCommandLine != TEXT('/0') && *pstrCommandLine != TEXT('/"')) ??????????? pstrCommandLine++; ???????? If( *pstrCommandLine == TEXT('/"') ) ??????????? pstrCommandLine++; ?????? } ????? else ????? { ? ??????while (*pstrCommandLine != TEXT('/0') && *pstrCommandLine != TEXT(' ')) ??????????? pstrCommandLine++; ???????? if( *pstrCommandLine == TEXT(' ') ) ??????????? pstrCommandLine++; ????? } ??? // 跳過"/" 或 "-" ??? while ( *pstrCommandLine != TEXT('/0') && *pstrCommandLine != TEXT('/') && *pstrCommandLine != TEXT('-') ) ??????? pstrCommandLine++; ??? // 如果沒有任何參數,為設置模式。 ??? if ( *pstrCommandLine == TEXT('/0') ) ??????? return sm_config; ??? // 如果有參數,查看參數內容。 ??? switch ( *(++pstrCommandLine) ) ???? { ??????? case 'c': ??????? case 'C': ??????????? pstrCommandLine++; ??????????? while ( *pstrCommandLine && !isdigit(*pstrCommandLine) ) ??????????????? pstrCommandLine++; ??????????? if ( isdigit(*pstrCommandLine) ) ??????????? { #ifdef _WIN64? //考慮64位編譯情況。 ??????????????? CHAR strCommandLine[2048]; ??????????????? DXUtil_ConvertGenericStringToAnsiCb( strCommandLine, pstrCommandLine, sizeof(strCommandLine)); //該函數僅在64位編譯情況下使用。 ??????????????? g_hWndParent = (HWND)(_atoi64(strCommandLine)); #else ??????????????? g_hWndParent = (HWND)LongToHandle(_ttol(pstrCommandLine)); //數字串變為/Window句柄 #endif ??????????? } ??????????? else ??????????? { ??????????????? g_hWndParent = NULL; ??????????? } ??????????? return sm_config; ??????? case 't': ??????? case 'T': ??????????? return sm_test; ??????? case 'p': ??????? case 'P': ??????????? //預覽模式,后面有Window句柄,為十進制數字 ??????????? pstrCommandLine++; ??????????? while ( *pstrCommandLine && !isdigit(*pstrCommandLine) ) ???? ???????????pstrCommandLine++; ??????????? if ( isdigit(*pstrCommandLine) ) ????????????? { #ifdef _WIN64 ??????????????? CHAR strCommandLine[2048]; ??????????????? DXUtil_ConvertGenericStringToAnsiCb(strCommandLine, pstrCommandLine, sizeof(strCommandLine)); ??????????????? g_hWndParent = (HWND)(_atoi64(strCommandLine)); #else ??????????????? g_hWndParent = (HWND)LongToHandle(_ttol(pstrCommandLine)); #endif ????????????? } ???????????? return sm_preview; ??????? case 'a': ??????? case 'A': ??????????? //密碼設置模式,后面有Window句柄,為十進制數字 ??????????? pstrCommandLine++; ??????????? while ( *pstrCommandLine && !isdigit(*pstrCommandLine) ) ??????????????? pstrCommandLine++; ??????????? if ( isdigit(*pstrCommandLine) ) ??????????? { #ifdef _WIN64 ??????????????? CHAR strCommandLine[2048]; ??????????????? DXUtil_ConvertGenericStringToAnsiCb(strCommandLine, pstrCommandLine, sizeof(strCommandLine)); ??????????????? g_hWndParent = (HWND)(_atoi64(strCommandLine)); #else ??????????????? g_hWndParent = (HWND)LongToHandle(_ttol(pstrCommandLine)); #endif ??????????? } ??????????? return sm_passwordchange; ??????? default: ??????????? //其他選項,屏保實際運行模式(通常/s) ??????????? return sm_full; ??? } } /// ParseCommandLine( ) 返回后,程序根據不同的返回值進行響應: 返回值=sm_preview或者sm_test 或者sm_full: 程序根據返回的運行模式和Window句柄使用CreateWindow函數創建窗口(Window)并返回指向該窗口的句柄。這部分功能包含在自定義的CreateSaverWindow()函數中。在sm_preview情況下,程序用消息循環的方式等待500ms使操作系統的控制面板有足夠的時間初始化。然后,讀注冊表檢查屏保是否設定了密碼,如果是,在Win9x情況下,用LoadLibrary()和GetProcessAdress()函數從動態鏈接庫(DLL)中獲得密碼驗證函數指針供程序退出時使用,密碼驗證函數類型為BOOL? PASCAL? (HWND)。這部分功能包含在自定義函數InitSaver()中。 以上窗口創建使用同一個窗口類(Window Class(WNDCLASS)),當然也是同一個消息響應函數(Window’s Procedure)。最后顯示窗口,開始消息循環。 返回值=sm_passwordchange: 用LoadLibrary()和 GetProcessAdress()API獲得密碼設置函數指針,密碼設置函數類型為:DOWORD? PASCAL? ( LPCSTR, HWND, DWORD, LPVOID ),然后調用該函數進行密碼更改。 返回值=sm_config 顯示一個對話框(Dialog),獲取用戶信息,在程序中進行相應的更改。 屏幕保護程序的退出機制反映在程序的消息響應函數(Window’s Procedure)中,當按下鍵盤上任何一個健或者鼠標移動計數超過5次(防止桌面振動等因素導致的鼠標移動),程序進入退出機制,在sm_test或者sm--_full情況下查看屏幕保護程序是否設置密碼,如果是,驗證密碼,正確,程序退出,錯誤,程序繼續。當程序驗證密碼時,通過全局變量g_bCheckingSaverPassword告訴消息響應函數對屏幕刷新,以保證密碼的輸入。其他情況(sm_config, sm_preview)不用驗證密碼直接退出。這些功能包括在自定義的函數InterruptSaver( )和ShutdownSaver( )中。 上述各個函數的詳細代碼如下: 1、?CreateSaverWindow 函數: HWND CreateSaverWindow(SaverMode mode, HWND hWndParent,HINSTANCE hInstance) { ??? HWND hWnd; ??? RECT rc; ??? DWORD dwStyle; ?????????????????????????? hWnd=NULL; ?????????????????????????? ??? switch ( mode ) ??? { ??????? case sm_preview: ??????????? GetClientRect(hWndParent, &rc ); ??????????? dwStyle = WS_VISIBLE | WS_CHILD; ??????????? AdjustWindowRect( &rc, dwStyle, FALSE ); ??????????? hWnd = CreateWindow( TEXT("SaverWndClass"), TEXT("SaverWindow"), dwStyle, ??????????????????????????????????? rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, ??????????????????????????????????? hWndParent, NULL, hInstance, NULL); ??????????? break; ?????? ?case sm_test: ??????????? rc.left = rc.top = 50; ??????????? rc.right = rc.left+600; ??????????? rc.bottom = rc.top+400; ??????????? dwStyle = WS_VISIBLE | WS_OVERLAPPED | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU; ??????????? AdjustWindowRect( &rc, dwStyle, FALSE ); ??????????? hWnd = CreateWindow( TEXT("SaverWndClass"), TEXT("SaverWindow"), dwStyle, ?????????????????????????????????? rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, ?????????????????????????????????? NULL, NULL, hInstance, NULL); ?? ?????????break; ??????? case sm_full: ??????????? ??????????? rc.left=rc.top=0; ???????????????????????????????????? rc.bottom=GetSystemMetrics(SM_CYSCREEN); ???????????????????????????????????? rc.right=GetSystemMetrics(SM_CXSCREEN); ???????????????????????????????????? dwStyle = WS_VISIBLE | WS_POPUP; ??????????? hWnd = CreateWindowEx( WS_EX_TOPMOST, TEXT("SaverWndClass"), ??????????????????? TEXT("SaverWindow"), dwStyle, rc.left, rc.top, rc.right - rc.left, ??????????????????? rc.bottom - rc.top, NULL, NULL, hInstance, NULL); ??????????????? ??? } ?????????????????????????? ??? if(mode == sm_preview ) ??? { ??????? // 開始預覽時,進入一個短暫的循環以使系統顯示控制面板有足夠的時間初始化 ??????? g_bWaitForInputIdle = TRUE; ??????? // 開始循環 ??????? PostMessage( g_hWnd, WM_USER, 0, 0 ); ??????? MSG msg; ??????? while( g_bWaitForInputIdle ) ??????? { ??????????? // 如果If 返回 FALSE, 結束循環 ??????????? if( !GetMessage( &msg, g_hWnd, 0, 0 ) ) ??????????? { ??????????????? // 結束循環 ??????????????? PostQuitMessage(0); ??????????????? break; ??????????? } ??????????? TranslateMessage( &msg); ??????????? DispatchMessage( &msg); ??????? } ??? } ??? ??? return hWnd; } 2、?Window消息響應函數: LRESULT CALLBACK SaverProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { ??? switch ( uMsg ) ??????? { ??????? case WM_USER: ??????????? //預覽開始循環,500ms空閑時間用于控制面板的初始化。 ??????????? SetTimer( hWnd, 1, 500, NULL ); ??????????? break; ??????? case WM_TIMER: ??????????? // 500ms時間到,預覽循環結束。 ??????????? g_bWaitForInputIdle = FALSE; ??????????? KillTimer( hWnd, 1 ); ??????????? break; ??????? case WM_DESTROY: ??????????? ShutdownSaver(); ??????????? break; ??????? case WM_SETCURSOR: ??? ????????if ( g_SaverMode == sm_full && !g_bCheckingSaverPassword ) ??????????? { ??????????????? //隱藏鼠標指針 ??????????????? SetCursor( NULL ); ??????????????? return TRUE; ??????????? } ??????????? break; ??????? case WM_PAINT: ??????? { ??????????? ????? ??????PAINTSTRUCT ps; ??????????? BeginPaint( hWnd, &ps ); ??????????????? RECT rc; ??????????????? GetClientRect(hWnd,&rc); ??????????????? FillRect(ps.hdc, &rc, (HBRUSH)GetStockObject(BLACK_BRUSH) ); //黑屏 ??????????? EndPaint( hWnd, &ps ); ??????? ????return 0; ??????? } ??????? case WM_ERASEBKGND: ??????????? // 輸入密碼時對屏幕刷新 ???????????? if( !g_bCheckingSaverPassword ) ??????????????? return TRUE;?? ?????????? ??????????? break; ??????? case WM_MOUSEMOVE: ??????????? if( g_SaverMode != sm_test ) ??????????? { ??????????????? static INT xPrev = -1; ??????????????? static INT yPrev = -1; ??????????????? INT xCur = GET_X_LPARAM(lParam); ??????????????? INT yCur = GET_Y_LPARAM(lParam); ??????????????? if( xCur != xPrev || yCur != yPrev ) ???????????? ???{ ??????????????????? xPrev = xCur; ??????????????????? yPrev = yCur; ??????????????????? g_dwSaverMouseMoveCount++; ??????????????????? if ( g_dwSaverMouseMoveCount > 5 ) ??????????????????????? InterruptSaver(); ??????????????? } ??????????? } ?????? ?????break; ??????? case WM_KEYDOWN: ??????? case WM_LBUTTONDOWN: ??????? case WM_RBUTTONDOWN: ??????? case WM_MBUTTONDOWN: ??????????? if( g_SaverMode != sm_test ) ??????????????? InterruptSaver(); ??????????? break; ??????? case WM_ACTIVATEAPP: ?????? ?????if( wParam == FALSE && g_SaverMode != sm_test ) ??????????????? InterruptSaver(); ??????????? break; ??????? case WM_POWERBROADCAST: ??????????? if( wParam == PBT_APMSUSPEND && g_VerifySaverPassword == NULL ) ??????????????? InterruptSaver(); ?????? ?????break; ??????? case WM_SYSCOMMAND: ??????????? if ( g_SaverMode == sm_full ) ??????????? { ??????????????? switch ( wParam ) ??????????????? { ??????????????????? case SC_NEXTWINDOW: ??????????????????? case SC_PREVWINDOW: ??????????????????? case SC_SCREENSAVE: ??????????????????? case SC_CLOSE: ??????????????????????? return FALSE; ??????????????? }; ??????????? } ??????????? break; ??? } ??? return DefWindowProc( hWnd, uMsg, wParam, lParam ); } 3、?ChangePassword()函數 VOID ChangePassword() { ??? // 載入密碼更改函數動態鏈接庫(Dynamic Linked Library) ??? HINSTANCE mpr = LoadLibrary( TEXT("MPR.DLL") ); ??? if ( mpr != NULL ) ??? { ??????? // 從動態鏈接數據庫中提取密碼設置函數 ??????? typedef DWORD (PASCAL *PWCHGPROC)( LPCSTR, HWND, DWORD, LPVOID ); ??????? PWCHGPROC pwd = (PWCHGPROC)GetProcAddress( mpr, "PwdChangePasswordA" ); ??????? //運行密碼設置函數 ??????? if ( pwd != NULL ) ??????????? pwd( "SCRSAVE", g_hWndParent, 0, NULL ); ??????? //釋放動態鏈接庫 ??????? FreeLibrary( mpr ); ??? } } 4、?InitSaver()函數 ??? VOID InitSaver() { //檢查操作系統版本 ??? OSVERSIONINFO osvi; ??????? osvi.dwOSVersionInfoSize = sizeof(osvi); ??????? GetVersionEx( &osvi ); ??????? g_bIs9x = (osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS); ?????? // 在運行模式下,如果操作系統是win9x,需要載入密碼驗證動態鏈接庫。 ???? ?if ( g_SaverMode == sm_full && g_bIs9x ) ?????? { ??????? // 檢查注冊表查看屏保是否設定了密碼 ??????? HKEY hKey; ??????? if ( RegCreateKeyEx( HKEY_CURRENT_USER, REGSTR_PATH_SCREENSAVE, 0, NULL, 0, KEY_READ, NULL, &hKey, NULL ) == ERROR_SUCCESS ) ?????????? { ???????? ???DWORD dwVal; ??????????? DWORD dwSize = sizeof(dwVal); ??????????? if ( (RegQueryValueEx( hKey, REGSTR_VALUE_USESCRPASSWORD, NULL, NULL, ?????????????????????????????????? (BYTE *)&dwVal, &dwSize ) == ERROR_SUCCESS) && dwVal ) ??????????? { ?????? ?????????g_hPasswordDLL = LoadLibrary( TEXT("PASSWORD.CPL") ); ??????????????? if ( g_hPasswordDLL ) ???????????????? g_VerifySaverPassword= (VERIFYPWDPROC)GetProcAddress( g_hPasswordDLL, "VerifyScreenSavePwd" ); ??????????????? RegCloseKey( hKey ); ????? ??????} ???????? } ????? } ?? ????? if ( g_SaverMode == sm_full ) ?????? { ???????? BOOL bUnused; ???????? SystemParametersInfo( SPI_SCREENSAVERRUNNING, TRUE, &bUnused, 0 ); //通知操作系統屏幕保護程序開始運行。 ?????? } } 5、屏保退出函數ShutdownSaver( )和InteruptSaver( ): VOID ShutdownSaver() { ??? // 通知操作系統屏幕保護程序退出 ??? if ( g_SaverMode == sm_full ) ???? { ??????? BOOL bUnused; ??????? SystemParametersInfo( SPI_SCREENSAVERRUNNING, FALSE, &bUnused, 0 ); ???? } ??? ??? if ( g_hPasswordDLL != NULL ) ???? { ??????? FreeLibrary( g_hPasswordDLL ); ??????? g_hPasswordDLL = NULL; ???? } ?? ???? PostQuitMessage( 0 ); } / VOID InterruptSaver() { ??? BOOL bPasswordOkay = FALSE; ??? if( g_SaverMode == sm_test || ??????? g_SaverMode == sm_full&&!g_bCheckingSaverPassword ) ??? { ??????? if( g_bIs9x && g_SaverMode == sm_full ) ??????? { ??????????? // Win9x下如果g_VerifySaverPassword==NULL,則沒有設屏保密碼。 ??????????? if ( g_VerifySaverPassword != NULL ) ??????????? { ??????????????? ????????????????????? g_bCheckingSaverPassword = TRUE;//告訴消息響應函數正在驗證密碼 ??????????????? bPasswordOkay = g_VerifySaverPassword( g_hWnd ); ???????????????????????????????????????????????????? g_bCheckingSaverPassword = FALSE; //密碼驗證結束。 ??????????????? if ( !bPasswordOkay ) ??????????????? { ?????????????????? //屏保程序繼續運行… ??????????????????? SetCursor( NULL ); ??????????????????? g_dwSaverMouseMoveCount = 0; ??????????????????? return; ??????????????? } ??????????? } ??????? } ??????? ShutdownSaver(); ??? } } 屏保設置方式下的響應程序為自定義Doconfig( ),因篇幅的關系不再詳細介紹,讀者應當很容易自己加上,也可以定義為空函數:VOID Doconfig ( ) { return;}。 黑屏屏幕保護程序主入口函數如下: #include <windows.h> #include <windowsx.h> #include <tchar.h> #include <stdio.h> #include <stdlib.h> #include <regstr.h> #include "Saver.h" #include "resource.h" HINSTANCE g_hinstance; HWND g_hWndParent; BOOL? g_bWaitForInputIdle; HWND g_hWnd; LRESULT CALLBACK SaverProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); int APIENTRY WinMain(HINSTANCE hInstance, ???????????????????? HINSTANCE hPrevInstance, ???????????????????? LPSTR???? lpCmdLine, ???????????????????? int?????? nCmdShow) { ????????????????????????? // TODO: Place code here. ??? ?????????????????????????? MSG msg; ?????????????????????????? g_bCheckingSaverPassword = FALSE; ??????????????? g_bIs9x = FALSE; ??????????????? g_dwSaverMouseMoveCount = 0; ??????????????? g_hWndParent = NULL; ??????????????? g_hPasswordDLL = NULL; ??????????????? g_hWnd = NULL; ??????????????? g_VerifySaverPassword = NULL; ??????????????? g_hinstance=hInstance; ??? ?????????????????????????? WNDCLASS??? cls; ??????????????? cls.hCursor = LoadCursor( NULL, IDC_ARROW ); ??????????????? cls.hIcon = LoadIcon( hInstance, MAKEINTRESOURCE(IDI_MAIN_ICON) ); ??????????????? cls.lpszMenuName = NULL; ??????????????? cls.lpszClassName = TEXT("SaverWndClass"); ??????????????? cls.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH); ??????????????? cls.hInstance = hInstance; ??????????????? cls.style = CS_VREDRAW|CS_HREDRAW; ??????????????? cls.lpfnWndProc = SaverProc; ???????????? ???cls.cbWndExtra = 0; ??????????????? cls.cbClsExtra = 0; ???????????? if(!RegisterClass( &cls )) ??????????????????????????????????? MessageBox(NULL,TEXT("Cant register window class"),TEXT("SaverWndClass"),MB_ICONERROR); ??? ?????????????????????????? SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_IDLE ); ??????????????? TCHAR* pstrCmdLine = GetCommandLine(); g_SaverMode = ParseCommandLine(pstrCmdLine); ?????????????????????????? switch(g_SaverMode) ?????????????????????????? { ?????? ?????????????????????????? case sm_preview: ?????????????????????????? case sm_full: ?????????????????????????? case sm_test: ?????????????????????????? ??? g_hWnd=CreateSaverWindow(g_SaverMode,g_hWndParent,hInstance); ?????????????????????????? ?????????????????????????? ??? if ( g_hWnd == NULL ) ?????????????????????????? ?? ???????? { ?????????????????????????????????????????????????????? MessageBox(NULL,TEXT("Can't Create Window"), TEXT("Create Window Terminated"),MB_ICONERROR); ?????????????????????????? ???????? return 0; ??????????????????????????????????? ??? }else ?????????????????????????? ??????????????????????????????????? ??? { ??????????????????????????????????? ????? ShowWindow(g_hWnd,nCmdShow); ??????????????????????????????????? ????? UpdateWindow(g_hWnd); ?????????????????????????? ?? ???????? } ?????????????????????????? ???????????????????? InitSaver(); ??? ?????????????????????????? ???? while(GetMessage(&msg,NULL,0,0)) ?????????????????????????? ?????? { ??????????????????????????????????? ??????? TranslateMessage(&msg); ??????????????????????????????????? ??????? DispatchMessage(&msg); ?????????????????????????? ??????? } ?????????????????????????? ?????? break; case sm_config: ? Doconfig(); ??????????????????????????????????? ?? break; ?????????????????????????? case sm_passwordchange: ??????????????????????????????????? ?? ChangePassword(); ?????????????????????????? ?? break; ??????????? } ?????????????????????????? ?????????????????????????? return 0; } 至此,黑屏屏幕保護程序代碼編寫完成,下一步是輸入VC++6.0 并進行編譯,具體步驟如下: 1、?打開VC++ 6.0, 從文件菜單中選擇 New, 選中工程(Project)窗口,從窗口中選中Win32 Application項,在右側的Locatioon(工程文件保存位置)填入位置信息(如填D/ScreenSaver),在其上邊的Project name(工程名)欄中填入適當的名稱(如Saver),按OK按鈕,這時出現新的窗口,有三個選項,選擇 A Simple Apllication, 按Finish(完成)健,接下來出現確認窗口,按OK,完成初步Win32 Application工程的創建。 2、?在ClassView窗口的Globles項下找到WinMain函數,雙擊鼠標打開C++文件(本文為Saver.cpp),按照前面的各條程序輸入相應內容。 3、?選擇FileView窗口選項,從主窗口文件菜單中選擇New,選擇File(文件),從文件類型中選擇C/C++ Header File,輸入文件名(最好與工程名同名,如Saver),確認后,新的頭文件出現在FileView窗口Header Files項下(本文文件名為Saver.h)。 雙擊新創建的頭文件(Saver.h),在頭文件中輸入以上函數和全局變量的說明(Declaration):
enum SaverMode { ??????? sm_config, ??????? sm_preview, ??????? sm_full, ??????? sm_test, ??????? sm_passwordchange }; typedef BOOL (PASCAL * VERIFYPWDPROC) (HWND); DWORD?????????? g_dwSaverMouseMoveCount; BOOL??????????? g_bIs9x; HINSTANCE?????? g_hPasswordDLL; VERIFYPWDPROC?? g_VerifySaverPassword; BOOL??????????? g_bCheckingSaverPassword; SaverMode?????? g_SaverMode; SaverMode ParseCommandLine( TCHAR* pstrCommandLine ); HWND CreateSaverWindow(SaverMode mode, HWND hWndParent,HINSTANCE hInstance); VOID InitSaver(); VOID ChangePassword(); VOID Doconfig( ); 4、?確保在C++主文件中包含頭文件,即在主文件(Saver.cpp)中,包含#include <Saver.h>語句。 5、?在插入(Insert)菜單中選擇資源(Resource),在隨后出現的菜單中選擇資源類型為圖標(Icon),按新建按鈕,這時,空白圖標出現在右邊窗口,對其進行編輯后,用鼠標選定該圖標,從查看菜單中打開屬性窗口(Properties),將該圖標的ID 改為IDI_MAIN_ICON,按保存按鈕,這時出現窗口,要求選擇Resource Script文件名,填入適當的文件名(本文填Saver),按OK健,這時,工程目錄中應當出現以rc為擴展名的文件。選擇FileView窗口,選擇Resource Files項,按鼠標右健,選擇Add Files to Folder…項,將Resource.h和新建立的Saver.rc文件加入Resource項下。這時,出現ResourceView窗口選項,從該窗口中可以查看本工程的資源(Resource)情況。 6、?在工程菜單中,選擇設置(Settings…), 在Setting for欄目中分別選擇Win32 Release和Win32 Debug項,在右邊的Link窗口中,將Output File Name中的文件名從exe擴展名改為scr擴展名。 這時,完成編譯環境的設置和輸入工作,從編譯菜單中選Build,如果沒有輸入錯誤,即可順利編譯成功。
測試方式,忽略句柄數字。 3.??? “運行模式”=‘p’或‘P’。
預覽方式,Window 顯示屬性_屏幕保護程序_預覽按鈕調用,句柄為調用函數的窗口句柄。 4.??? “運行模式”=‘a’或‘A’。
密碼設置方式, Window 顯示屬性_屏幕保護程序_密碼保護_更改按鈕調用。句柄為調用函數的Window 句柄。 5.??? 其它(通常“運行模式”=‘s’)
屏幕保護程序正常運行模式。 因此,編寫屏幕保護程序的首要任務是過濾命令行,提取對應的系統調用方式和其他信息,本文用自定義函數ParseCommandline( )實現: //用enum定義五種調用方式: enum SaverMode { ??????????????????????????????????? sm_config, ??????????????????????????????????? sm_preview, ??????????????????????????????????? sm_full, ??????????????????????????????????? sm_test, ??????????????????????????????????? sm_passwordchange }; ? //命令行過濾函數,命令行獲得函數是用API ?GetCommandLine( )。 SaverMode ParseCommandLine( TCHAR* pstrCommandLine ) { ????? g_hWndParent = NULL; //全局變量(global varibale) 在頭函數或主文件開始處定義。 ????? // 跳過長文件名中的路徑和空格。 ????? if (*pstrCommandLine == TEXT('/"')) ?????? { ???????? pstrCommandLine++; ???????? while (*pstrCommandLine != TEXT('/0') && *pstrCommandLine != TEXT('/"')) ??????????? pstrCommandLine++; ???????? If( *pstrCommandLine == TEXT('/"') ) ??????????? pstrCommandLine++; ?????? } ????? else ????? { ? ??????while (*pstrCommandLine != TEXT('/0') && *pstrCommandLine != TEXT(' ')) ??????????? pstrCommandLine++; ???????? if( *pstrCommandLine == TEXT(' ') ) ??????????? pstrCommandLine++; ????? } ??? // 跳過"/" 或 "-" ??? while ( *pstrCommandLine != TEXT('/0') && *pstrCommandLine != TEXT('/') && *pstrCommandLine != TEXT('-') ) ??????? pstrCommandLine++; ??? // 如果沒有任何參數,為設置模式。 ??? if ( *pstrCommandLine == TEXT('/0') ) ??????? return sm_config; ??? // 如果有參數,查看參數內容。 ??? switch ( *(++pstrCommandLine) ) ???? { ??????? case 'c': ??????? case 'C': ??????????? pstrCommandLine++; ??????????? while ( *pstrCommandLine && !isdigit(*pstrCommandLine) ) ??????????????? pstrCommandLine++; ??????????? if ( isdigit(*pstrCommandLine) ) ??????????? { #ifdef _WIN64? //考慮64位編譯情況。 ??????????????? CHAR strCommandLine[2048]; ??????????????? DXUtil_ConvertGenericStringToAnsiCb( strCommandLine, pstrCommandLine, sizeof(strCommandLine)); //該函數僅在64位編譯情況下使用。 ??????????????? g_hWndParent = (HWND)(_atoi64(strCommandLine)); #else ??????????????? g_hWndParent = (HWND)LongToHandle(_ttol(pstrCommandLine)); //數字串變為/Window句柄 #endif ??????????? } ??????????? else ??????????? { ??????????????? g_hWndParent = NULL; ??????????? } ??????????? return sm_config; ??????? case 't': ??????? case 'T': ??????????? return sm_test; ??????? case 'p': ??????? case 'P': ??????????? //預覽模式,后面有Window句柄,為十進制數字 ??????????? pstrCommandLine++; ??????????? while ( *pstrCommandLine && !isdigit(*pstrCommandLine) ) ???? ???????????pstrCommandLine++; ??????????? if ( isdigit(*pstrCommandLine) ) ????????????? { #ifdef _WIN64 ??????????????? CHAR strCommandLine[2048]; ??????????????? DXUtil_ConvertGenericStringToAnsiCb(strCommandLine, pstrCommandLine, sizeof(strCommandLine)); ??????????????? g_hWndParent = (HWND)(_atoi64(strCommandLine)); #else ??????????????? g_hWndParent = (HWND)LongToHandle(_ttol(pstrCommandLine)); #endif ????????????? } ???????????? return sm_preview; ??????? case 'a': ??????? case 'A': ??????????? //密碼設置模式,后面有Window句柄,為十進制數字 ??????????? pstrCommandLine++; ??????????? while ( *pstrCommandLine && !isdigit(*pstrCommandLine) ) ??????????????? pstrCommandLine++; ??????????? if ( isdigit(*pstrCommandLine) ) ??????????? { #ifdef _WIN64 ??????????????? CHAR strCommandLine[2048]; ??????????????? DXUtil_ConvertGenericStringToAnsiCb(strCommandLine, pstrCommandLine, sizeof(strCommandLine)); ??????????????? g_hWndParent = (HWND)(_atoi64(strCommandLine)); #else ??????????????? g_hWndParent = (HWND)LongToHandle(_ttol(pstrCommandLine)); #endif ??????????? } ??????????? return sm_passwordchange; ??????? default: ??????????? //其他選項,屏保實際運行模式(通常/s) ??????????? return sm_full; ??? } } /// ParseCommandLine( ) 返回后,程序根據不同的返回值進行響應: 返回值=sm_preview或者sm_test 或者sm_full: 程序根據返回的運行模式和Window句柄使用CreateWindow函數創建窗口(Window)并返回指向該窗口的句柄。這部分功能包含在自定義的CreateSaverWindow()函數中。在sm_preview情況下,程序用消息循環的方式等待500ms使操作系統的控制面板有足夠的時間初始化。然后,讀注冊表檢查屏保是否設定了密碼,如果是,在Win9x情況下,用LoadLibrary()和GetProcessAdress()函數從動態鏈接庫(DLL)中獲得密碼驗證函數指針供程序退出時使用,密碼驗證函數類型為BOOL? PASCAL? (HWND)。這部分功能包含在自定義函數InitSaver()中。 以上窗口創建使用同一個窗口類(Window Class(WNDCLASS)),當然也是同一個消息響應函數(Window’s Procedure)。最后顯示窗口,開始消息循環。 返回值=sm_passwordchange: 用LoadLibrary()和 GetProcessAdress()API獲得密碼設置函數指針,密碼設置函數類型為:DOWORD? PASCAL? ( LPCSTR, HWND, DWORD, LPVOID ),然后調用該函數進行密碼更改。 返回值=sm_config 顯示一個對話框(Dialog),獲取用戶信息,在程序中進行相應的更改。 屏幕保護程序的退出機制反映在程序的消息響應函數(Window’s Procedure)中,當按下鍵盤上任何一個健或者鼠標移動計數超過5次(防止桌面振動等因素導致的鼠標移動),程序進入退出機制,在sm_test或者sm--_full情況下查看屏幕保護程序是否設置密碼,如果是,驗證密碼,正確,程序退出,錯誤,程序繼續。當程序驗證密碼時,通過全局變量g_bCheckingSaverPassword告訴消息響應函數對屏幕刷新,以保證密碼的輸入。其他情況(sm_config, sm_preview)不用驗證密碼直接退出。這些功能包括在自定義的函數InterruptSaver( )和ShutdownSaver( )中。 上述各個函數的詳細代碼如下: 1、?CreateSaverWindow 函數: HWND CreateSaverWindow(SaverMode mode, HWND hWndParent,HINSTANCE hInstance) { ??? HWND hWnd; ??? RECT rc; ??? DWORD dwStyle; ?????????????????????????? hWnd=NULL; ?????????????????????????? ??? switch ( mode ) ??? { ??????? case sm_preview: ??????????? GetClientRect(hWndParent, &rc ); ??????????? dwStyle = WS_VISIBLE | WS_CHILD; ??????????? AdjustWindowRect( &rc, dwStyle, FALSE ); ??????????? hWnd = CreateWindow( TEXT("SaverWndClass"), TEXT("SaverWindow"), dwStyle, ??????????????????????????????????? rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, ??????????????????????????????????? hWndParent, NULL, hInstance, NULL); ??????????? break; ?????? ?case sm_test: ??????????? rc.left = rc.top = 50; ??????????? rc.right = rc.left+600; ??????????? rc.bottom = rc.top+400; ??????????? dwStyle = WS_VISIBLE | WS_OVERLAPPED | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU; ??????????? AdjustWindowRect( &rc, dwStyle, FALSE ); ??????????? hWnd = CreateWindow( TEXT("SaverWndClass"), TEXT("SaverWindow"), dwStyle, ?????????????????????????????????? rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, ?????????????????????????????????? NULL, NULL, hInstance, NULL); ?? ?????????break; ??????? case sm_full: ??????????? ??????????? rc.left=rc.top=0; ???????????????????????????????????? rc.bottom=GetSystemMetrics(SM_CYSCREEN); ???????????????????????????????????? rc.right=GetSystemMetrics(SM_CXSCREEN); ???????????????????????????????????? dwStyle = WS_VISIBLE | WS_POPUP; ??????????? hWnd = CreateWindowEx( WS_EX_TOPMOST, TEXT("SaverWndClass"), ??????????????????? TEXT("SaverWindow"), dwStyle, rc.left, rc.top, rc.right - rc.left, ??????????????????? rc.bottom - rc.top, NULL, NULL, hInstance, NULL); ??????????????? ??? } ?????????????????????????? ??? if(mode == sm_preview ) ??? { ??????? // 開始預覽時,進入一個短暫的循環以使系統顯示控制面板有足夠的時間初始化 ??????? g_bWaitForInputIdle = TRUE; ??????? // 開始循環 ??????? PostMessage( g_hWnd, WM_USER, 0, 0 ); ??????? MSG msg; ??????? while( g_bWaitForInputIdle ) ??????? { ??????????? // 如果If 返回 FALSE, 結束循環 ??????????? if( !GetMessage( &msg, g_hWnd, 0, 0 ) ) ??????????? { ??????????????? // 結束循環 ??????????????? PostQuitMessage(0); ??????????????? break; ??????????? } ??????????? TranslateMessage( &msg); ??????????? DispatchMessage( &msg); ??????? } ??? } ??? ??? return hWnd; } 2、?Window消息響應函數: LRESULT CALLBACK SaverProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { ??? switch ( uMsg ) ??????? { ??????? case WM_USER: ??????????? //預覽開始循環,500ms空閑時間用于控制面板的初始化。 ??????????? SetTimer( hWnd, 1, 500, NULL ); ??????????? break; ??????? case WM_TIMER: ??????????? // 500ms時間到,預覽循環結束。 ??????????? g_bWaitForInputIdle = FALSE; ??????????? KillTimer( hWnd, 1 ); ??????????? break; ??????? case WM_DESTROY: ??????????? ShutdownSaver(); ??????????? break; ??????? case WM_SETCURSOR: ??? ????????if ( g_SaverMode == sm_full && !g_bCheckingSaverPassword ) ??????????? { ??????????????? //隱藏鼠標指針 ??????????????? SetCursor( NULL ); ??????????????? return TRUE; ??????????? } ??????????? break; ??????? case WM_PAINT: ??????? { ??????????? ????? ??????PAINTSTRUCT ps; ??????????? BeginPaint( hWnd, &ps ); ??????????????? RECT rc; ??????????????? GetClientRect(hWnd,&rc); ??????????????? FillRect(ps.hdc, &rc, (HBRUSH)GetStockObject(BLACK_BRUSH) ); //黑屏 ??????????? EndPaint( hWnd, &ps ); ??????? ????return 0; ??????? } ??????? case WM_ERASEBKGND: ??????????? // 輸入密碼時對屏幕刷新 ???????????? if( !g_bCheckingSaverPassword ) ??????????????? return TRUE;?? ?????????? ??????????? break; ??????? case WM_MOUSEMOVE: ??????????? if( g_SaverMode != sm_test ) ??????????? { ??????????????? static INT xPrev = -1; ??????????????? static INT yPrev = -1; ??????????????? INT xCur = GET_X_LPARAM(lParam); ??????????????? INT yCur = GET_Y_LPARAM(lParam); ??????????????? if( xCur != xPrev || yCur != yPrev ) ???????????? ???{ ??????????????????? xPrev = xCur; ??????????????????? yPrev = yCur; ??????????????????? g_dwSaverMouseMoveCount++; ??????????????????? if ( g_dwSaverMouseMoveCount > 5 ) ??????????????????????? InterruptSaver(); ??????????????? } ??????????? } ?????? ?????break; ??????? case WM_KEYDOWN: ??????? case WM_LBUTTONDOWN: ??????? case WM_RBUTTONDOWN: ??????? case WM_MBUTTONDOWN: ??????????? if( g_SaverMode != sm_test ) ??????????????? InterruptSaver(); ??????????? break; ??????? case WM_ACTIVATEAPP: ?????? ?????if( wParam == FALSE && g_SaverMode != sm_test ) ??????????????? InterruptSaver(); ??????????? break; ??????? case WM_POWERBROADCAST: ??????????? if( wParam == PBT_APMSUSPEND && g_VerifySaverPassword == NULL ) ??????????????? InterruptSaver(); ?????? ?????break; ??????? case WM_SYSCOMMAND: ??????????? if ( g_SaverMode == sm_full ) ??????????? { ??????????????? switch ( wParam ) ??????????????? { ??????????????????? case SC_NEXTWINDOW: ??????????????????? case SC_PREVWINDOW: ??????????????????? case SC_SCREENSAVE: ??????????????????? case SC_CLOSE: ??????????????????????? return FALSE; ??????????????? }; ??????????? } ??????????? break; ??? } ??? return DefWindowProc( hWnd, uMsg, wParam, lParam ); } 3、?ChangePassword()函數 VOID ChangePassword() { ??? // 載入密碼更改函數動態鏈接庫(Dynamic Linked Library) ??? HINSTANCE mpr = LoadLibrary( TEXT("MPR.DLL") ); ??? if ( mpr != NULL ) ??? { ??????? // 從動態鏈接數據庫中提取密碼設置函數 ??????? typedef DWORD (PASCAL *PWCHGPROC)( LPCSTR, HWND, DWORD, LPVOID ); ??????? PWCHGPROC pwd = (PWCHGPROC)GetProcAddress( mpr, "PwdChangePasswordA" ); ??????? //運行密碼設置函數 ??????? if ( pwd != NULL ) ??????????? pwd( "SCRSAVE", g_hWndParent, 0, NULL ); ??????? //釋放動態鏈接庫 ??????? FreeLibrary( mpr ); ??? } } 4、?InitSaver()函數 ??? VOID InitSaver() { //檢查操作系統版本 ??? OSVERSIONINFO osvi; ??????? osvi.dwOSVersionInfoSize = sizeof(osvi); ??????? GetVersionEx( &osvi ); ??????? g_bIs9x = (osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS); ?????? // 在運行模式下,如果操作系統是win9x,需要載入密碼驗證動態鏈接庫。 ???? ?if ( g_SaverMode == sm_full && g_bIs9x ) ?????? { ??????? // 檢查注冊表查看屏保是否設定了密碼 ??????? HKEY hKey; ??????? if ( RegCreateKeyEx( HKEY_CURRENT_USER, REGSTR_PATH_SCREENSAVE, 0, NULL, 0, KEY_READ, NULL, &hKey, NULL ) == ERROR_SUCCESS ) ?????????? { ???????? ???DWORD dwVal; ??????????? DWORD dwSize = sizeof(dwVal); ??????????? if ( (RegQueryValueEx( hKey, REGSTR_VALUE_USESCRPASSWORD, NULL, NULL, ?????????????????????????????????? (BYTE *)&dwVal, &dwSize ) == ERROR_SUCCESS) && dwVal ) ??????????? { ?????? ?????????g_hPasswordDLL = LoadLibrary( TEXT("PASSWORD.CPL") ); ??????????????? if ( g_hPasswordDLL ) ???????????????? g_VerifySaverPassword= (VERIFYPWDPROC)GetProcAddress( g_hPasswordDLL, "VerifyScreenSavePwd" ); ??????????????? RegCloseKey( hKey ); ????? ??????} ???????? } ????? } ?? ????? if ( g_SaverMode == sm_full ) ?????? { ???????? BOOL bUnused; ???????? SystemParametersInfo( SPI_SCREENSAVERRUNNING, TRUE, &bUnused, 0 ); //通知操作系統屏幕保護程序開始運行。 ?????? } } 5、屏保退出函數ShutdownSaver( )和InteruptSaver( ): VOID ShutdownSaver() { ??? // 通知操作系統屏幕保護程序退出 ??? if ( g_SaverMode == sm_full ) ???? { ??????? BOOL bUnused; ??????? SystemParametersInfo( SPI_SCREENSAVERRUNNING, FALSE, &bUnused, 0 ); ???? } ??? ??? if ( g_hPasswordDLL != NULL ) ???? { ??????? FreeLibrary( g_hPasswordDLL ); ??????? g_hPasswordDLL = NULL; ???? } ?? ???? PostQuitMessage( 0 ); } / VOID InterruptSaver() { ??? BOOL bPasswordOkay = FALSE; ??? if( g_SaverMode == sm_test || ??????? g_SaverMode == sm_full&&!g_bCheckingSaverPassword ) ??? { ??????? if( g_bIs9x && g_SaverMode == sm_full ) ??????? { ??????????? // Win9x下如果g_VerifySaverPassword==NULL,則沒有設屏保密碼。 ??????????? if ( g_VerifySaverPassword != NULL ) ??????????? { ??????????????? ????????????????????? g_bCheckingSaverPassword = TRUE;//告訴消息響應函數正在驗證密碼 ??????????????? bPasswordOkay = g_VerifySaverPassword( g_hWnd ); ???????????????????????????????????????????????????? g_bCheckingSaverPassword = FALSE; //密碼驗證結束。 ??????????????? if ( !bPasswordOkay ) ??????????????? { ?????????????????? //屏保程序繼續運行… ??????????????????? SetCursor( NULL ); ??????????????????? g_dwSaverMouseMoveCount = 0; ??????????????????? return; ??????????????? } ??????????? } ??????? } ??????? ShutdownSaver(); ??? } } 屏保設置方式下的響應程序為自定義Doconfig( ),因篇幅的關系不再詳細介紹,讀者應當很容易自己加上,也可以定義為空函數:VOID Doconfig ( ) { return;}。 黑屏屏幕保護程序主入口函數如下: #include <windows.h> #include <windowsx.h> #include <tchar.h> #include <stdio.h> #include <stdlib.h> #include <regstr.h> #include "Saver.h" #include "resource.h" HINSTANCE g_hinstance; HWND g_hWndParent; BOOL? g_bWaitForInputIdle; HWND g_hWnd; LRESULT CALLBACK SaverProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); int APIENTRY WinMain(HINSTANCE hInstance, ???????????????????? HINSTANCE hPrevInstance, ???????????????????? LPSTR???? lpCmdLine, ???????????????????? int?????? nCmdShow) { ????????????????????????? // TODO: Place code here. ??? ?????????????????????????? MSG msg; ?????????????????????????? g_bCheckingSaverPassword = FALSE; ??????????????? g_bIs9x = FALSE; ??????????????? g_dwSaverMouseMoveCount = 0; ??????????????? g_hWndParent = NULL; ??????????????? g_hPasswordDLL = NULL; ??????????????? g_hWnd = NULL; ??????????????? g_VerifySaverPassword = NULL; ??????????????? g_hinstance=hInstance; ??? ?????????????????????????? WNDCLASS??? cls; ??????????????? cls.hCursor = LoadCursor( NULL, IDC_ARROW ); ??????????????? cls.hIcon = LoadIcon( hInstance, MAKEINTRESOURCE(IDI_MAIN_ICON) ); ??????????????? cls.lpszMenuName = NULL; ??????????????? cls.lpszClassName = TEXT("SaverWndClass"); ??????????????? cls.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH); ??????????????? cls.hInstance = hInstance; ??????????????? cls.style = CS_VREDRAW|CS_HREDRAW; ??????????????? cls.lpfnWndProc = SaverProc; ???????????? ???cls.cbWndExtra = 0; ??????????????? cls.cbClsExtra = 0; ???????????? if(!RegisterClass( &cls )) ??????????????????????????????????? MessageBox(NULL,TEXT("Cant register window class"),TEXT("SaverWndClass"),MB_ICONERROR); ??? ?????????????????????????? SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_IDLE ); ??????????????? TCHAR* pstrCmdLine = GetCommandLine(); g_SaverMode = ParseCommandLine(pstrCmdLine); ?????????????????????????? switch(g_SaverMode) ?????????????????????????? { ?????? ?????????????????????????? case sm_preview: ?????????????????????????? case sm_full: ?????????????????????????? case sm_test: ?????????????????????????? ??? g_hWnd=CreateSaverWindow(g_SaverMode,g_hWndParent,hInstance); ?????????????????????????? ?????????????????????????? ??? if ( g_hWnd == NULL ) ?????????????????????????? ?? ???????? { ?????????????????????????????????????????????????????? MessageBox(NULL,TEXT("Can't Create Window"), TEXT("Create Window Terminated"),MB_ICONERROR); ?????????????????????????? ???????? return 0; ??????????????????????????????????? ??? }else ?????????????????????????? ??????????????????????????????????? ??? { ??????????????????????????????????? ????? ShowWindow(g_hWnd,nCmdShow); ??????????????????????????????????? ????? UpdateWindow(g_hWnd); ?????????????????????????? ?? ???????? } ?????????????????????????? ???????????????????? InitSaver(); ??? ?????????????????????????? ???? while(GetMessage(&msg,NULL,0,0)) ?????????????????????????? ?????? { ??????????????????????????????????? ??????? TranslateMessage(&msg); ??????????????????????????????????? ??????? DispatchMessage(&msg); ?????????????????????????? ??????? } ?????????????????????????? ?????? break; case sm_config: ? Doconfig(); ??????????????????????????????????? ?? break; ?????????????????????????? case sm_passwordchange: ??????????????????????????????????? ?? ChangePassword(); ?????????????????????????? ?? break; ??????????? } ?????????????????????????? ?????????????????????????? return 0; } 至此,黑屏屏幕保護程序代碼編寫完成,下一步是輸入VC++6.0 并進行編譯,具體步驟如下: 1、?打開VC++ 6.0, 從文件菜單中選擇 New, 選中工程(Project)窗口,從窗口中選中Win32 Application項,在右側的Locatioon(工程文件保存位置)填入位置信息(如填D/ScreenSaver),在其上邊的Project name(工程名)欄中填入適當的名稱(如Saver),按OK按鈕,這時出現新的窗口,有三個選項,選擇 A Simple Apllication, 按Finish(完成)健,接下來出現確認窗口,按OK,完成初步Win32 Application工程的創建。 2、?在ClassView窗口的Globles項下找到WinMain函數,雙擊鼠標打開C++文件(本文為Saver.cpp),按照前面的各條程序輸入相應內容。 3、?選擇FileView窗口選項,從主窗口文件菜單中選擇New,選擇File(文件),從文件類型中選擇C/C++ Header File,輸入文件名(最好與工程名同名,如Saver),確認后,新的頭文件出現在FileView窗口Header Files項下(本文文件名為Saver.h)。 雙擊新創建的頭文件(Saver.h),在頭文件中輸入以上函數和全局變量的說明(Declaration):
enum SaverMode { ??????? sm_config, ??????? sm_preview, ??????? sm_full, ??????? sm_test, ??????? sm_passwordchange }; typedef BOOL (PASCAL * VERIFYPWDPROC) (HWND); DWORD?????????? g_dwSaverMouseMoveCount; BOOL??????????? g_bIs9x; HINSTANCE?????? g_hPasswordDLL; VERIFYPWDPROC?? g_VerifySaverPassword; BOOL??????????? g_bCheckingSaverPassword; SaverMode?????? g_SaverMode; SaverMode ParseCommandLine( TCHAR* pstrCommandLine ); HWND CreateSaverWindow(SaverMode mode, HWND hWndParent,HINSTANCE hInstance); VOID InitSaver(); VOID ChangePassword(); VOID Doconfig( ); 4、?確保在C++主文件中包含頭文件,即在主文件(Saver.cpp)中,包含#include <Saver.h>語句。 5、?在插入(Insert)菜單中選擇資源(Resource),在隨后出現的菜單中選擇資源類型為圖標(Icon),按新建按鈕,這時,空白圖標出現在右邊窗口,對其進行編輯后,用鼠標選定該圖標,從查看菜單中打開屬性窗口(Properties),將該圖標的ID 改為IDI_MAIN_ICON,按保存按鈕,這時出現窗口,要求選擇Resource Script文件名,填入適當的文件名(本文填Saver),按OK健,這時,工程目錄中應當出現以rc為擴展名的文件。選擇FileView窗口,選擇Resource Files項,按鼠標右健,選擇Add Files to Folder…項,將Resource.h和新建立的Saver.rc文件加入Resource項下。這時,出現ResourceView窗口選項,從該窗口中可以查看本工程的資源(Resource)情況。 6、?在工程菜單中,選擇設置(Settings…), 在Setting for欄目中分別選擇Win32 Release和Win32 Debug項,在右邊的Link窗口中,將Output File Name中的文件名從exe擴展名改為scr擴展名。 這時,完成編譯環境的設置和輸入工作,從編譯菜單中選Build,如果沒有輸入錯誤,即可順利編譯成功。
總結
以上是生活随笔為你收集整理的用VC++6.0 编写一个完整的的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 最新研究前线-深度推荐系统真的有效吗?
- 下一篇: On Error Resume Next