参考网址:
https://blog.csdn.net/xylary/article/details/1737627
https://www.windows-commandline.com/configure-screensaver-command-line/
https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-systemparametersinfow
一 编写屏幕保护程序
微软已经写了一个静态类库ScrnSav.lib, 只要包含头文件, 实现几个接口就可以做出一个屏保来, 相关代码如下:
注意: 屏幕保护程序实际是个exe, 但是使用的时候要把exe改成scr, 并且放在 windowssystem32 或者windowssyswow64目录下
1 #include <Windows.h> 2 #include <ScrnSave.h> 3 4 #ifdef UNICODE 5 #pragma comment(lib, "ScrnSavw.lib") 6 #else 7 #pragma comment(lib, "ScrnSave.lib") 8 #endif 9 #pragma comment(lib,"comctl32.lib") 10 11 extern "C" LRESULT WINAPI ScreenSaverProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 12 { 13 switch (message) 14 {// 省略的代码 15 default: 16 return DefScreenSaverProc(hWnd, message, wParam, lParam); 17 } 18 return 0; 19 } 20 21 extern "C" BOOL WINAPI ScreenSaverConfigureDialog(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 22 {//暂时不需要配置对话框,仅返回FALSE 23 return FALSE; 24 } 25 26 extern "C" BOOL WINAPI RegisterDialogClasses(HANDLE hInstance) 27 {//一般不需要,仅返回TRUE 28 return TRUE; 29 }
二 设置屏保
1 拷贝文件到系统目录
2 设置注册表, 这个大多数是给系统重启后初始化屏保逻辑的初始参数
3 调用SystemParametersInfo api给各窗口发消息, 因为屏保的部分逻辑已经运行在当前已经运行的窗口程序中了, 需要调用此api给窗口发消息更新这些参数
代码如下:
1 #include <windows.h> 2 #include <strsafe.h> 3 #include <iostream> 4 5 bool GetScreenSaverRunning(bool &isRunning) 6 { 7 bool result = false; 8 try 9 { 10 BOOL BRun = TRUE; 11 BOOL ret = SystemParametersInfoW(SPI_GETSCREENSAVERRUNNING, NULL, &BRun, 0); 12 if (ret) 13 { 14 isRunning = BRun ? true : false; 15 result = true; 16 } 17 } 18 catch (...) 19 { 20 result = false; 21 } 22 return result; 23 } 24 bool GetScreenSaverActive(bool &active) 25 { 26 bool result = false; 27 try 28 { 29 BOOL bActive = TRUE; 30 BOOL ret = SystemParametersInfoW(SPI_GETSCREENSAVEACTIVE, NULL, &bActive, 0); 31 if (ret) 32 { 33 active = bActive ? true : false; 34 result = true; 35 } 36 } 37 catch (...) 38 { 39 result = false; 40 } 41 return result; 42 } 43 bool SetScreenSaverActive(bool active) 44 { 45 bool result = false; 46 try 47 { 48 BOOL ret = FALSE; 49 if (active) 50 ret = SystemParametersInfoW(SPI_SETSCREENSAVEACTIVE, TRUE, NULL, SPIF_SENDWININICHANGE); 51 else 52 ret = SystemParametersInfoW(SPI_SETSCREENSAVEACTIVE, FALSE, NULL, SPIF_SENDWININICHANGE); 53 54 result = ret ? true : false; 55 } 56 catch (...) 57 { 58 result = false; 59 } 60 return result; 61 } 62 63 //screenSaveTimeoutSeconds, 单位是秒 64 bool SetScreenSaver(const wchar_t *scrFile, UINT screenSaveTimeoutSeconds) 65 { 66 if (!scrFile || !screenSaveTimeoutSeconds) 67 return false; 68 69 bool result = false; 70 HRESULT hr = S_OK; 71 LSTATUS status = ERROR_SUCCESS; 72 BOOL ret2 = FALSE; 73 wchar_t buffer[MAX_PATH] = { 0 }; 74 DWORD accessmask = KEY_SET_VALUE; 75 HKEY root = NULL; 76 DWORD charLen = 0; 77 do 78 { 79 // copy到系统路径 80 BOOL isWOW64 = FALSE; 81 IsWow64Process(GetCurrentProcess(), &isWOW64); 82 83 UINT ret = 0; 84 if (isWOW64) 85 ret = GetSystemWow64DirectoryW(buffer, MAX_PATH); 86 else 87 ret = GetSystemDirectoryW(buffer, MAX_PATH); 88 if(ret ==0 || ret >MAX_PATH) 89 break; 90 91 hr = StringCchCatW(buffer, MAX_PATH, L"\aaa.scr"); 92 if(hr != S_OK) 93 break; 94 95 ret2 = CopyFile(scrFile, buffer, FALSE); 96 if(!ret2) 97 { 98 wchar_t buffer2[MAX_PATH] = { 0 }; 99 hr =StringCchPrintfW(buffer2, MAX_PATH, L"%s1",buffer); 100 if(hr != S_OK) 101 break; 102 103 ret2 =MoveFileExW(buffer, buffer2, MOVEFILE_REPLACE_EXISTING); 104 if (!ret2) 105 break; 106 107 ret2 = MoveFileExW(buffer2, NULL, MOVEFILE_DELAY_UNTIL_REBOOT); 108 if(!ret2) 109 break; 110 111 ret2 = CopyFile(scrFile, buffer, FALSE); 112 if (!ret2) 113 break; 114 } 115 116 status = RegOpenKeyExW(HKEY_CURRENT_USER, L"Control Panel", 0, accessmask, &root); 117 if(status != ERROR_SUCCESS) 118 break; 119 120 // 设置屏保程序 121 charLen = (DWORD)((wcslen(buffer) + 1) * sizeof(wchar_t)); 122 status = RegSetKeyValueW(root, L"Desktop", L"SCRNSAVE.EXE", REG_SZ, buffer, charLen); 123 if (status != ERROR_SUCCESS) 124 break; 125 126 // 设置超时时间 127 // 仅设置注册表不会立即生效, 要给其他程序发消息才能立即生效 128 hr = StringCchPrintfW(buffer, MAX_PATH, L"%u", screenSaveTimeoutSeconds); 129 if(hr !=S_OK) 130 break; 131 132 charLen = (DWORD)((wcslen(buffer) + 1) * sizeof(wchar_t)); 133 status = RegSetKeyValueW(root, L"Desktop", L"ScreenSaveTimeOut", REG_SZ, buffer, charLen); 134 if(status != ERROR_SUCCESS) 135 break; 136 137 try 138 { 139 ret2 = SystemParametersInfoW(SPI_SETSCREENSAVETIMEOUT, screenSaveTimeoutSeconds, NULL, SPIF_SENDWININICHANGE); 140 if (!ret2) 141 break; 142 } 143 catch (...) 144 { 145 break; 146 } 147 148 // 设置恢复时显示登录界面 149 // 仅设置注册表会立即生效, 但是设置界面跟注册表里的值不一致 150 hr = StringCchPrintfW(buffer, MAX_PATH, L"%u", 1); 151 if(hr != S_OK) 152 break; 153 154 charLen = (DWORD)((wcslen(buffer) + 1) * sizeof(wchar_t)); 155 status = RegSetKeyValueW(root, L"Desktop", L"ScreenSaverIsSecure", REG_SZ, buffer, charLen); 156 if(status !=ERROR_SUCCESS) 157 break; 158 159 try 160 { 161 BOOL bSecurite = TRUE; 162 ret2 = SystemParametersInfoW(SPI_SETSCREENSAVESECURE, bSecurite, NULL, SPIF_SENDWININICHANGE); 163 if (!ret2) 164 break; 165 } 166 catch (...) 167 { 168 break; 169 } 170 171 // 设置屏保开关 172 // 仅设置注册表不会立即生效, 要给其他程序发消息才能立即生效 173 hr = StringCchPrintfW(buffer, MAX_PATH, L"%u", 1); 174 if(hr != S_OK) 175 break; 176 177 charLen = (DWORD)((wcslen(buffer) + 1) * sizeof(wchar_t)); 178 status = RegSetKeyValueW(root, L"Desktop", L"ScreenSaveActive", REG_SZ, buffer, charLen); 179 if (status != ERROR_SUCCESS) 180 break; 181 182 SetScreenSaverActive(true); 183 184 result = true; 185 } while (false); 186 187 188 return result; 189 } 190 int main(int argc, char **argv, char **env) 191 { 192 SetScreenSaver(L"aaa.exe",60); 193 system("pause"); 194 return 0; 195 }