1 // 2 // screensave.c 3 // 4 // Entrypoint for a win32 screensaver 5 // 6 // NOTES: Screen savers don't like being UPX'd (compressed). Don't 7 // know why, it just is. C-runtime has been stripped with 8 // "libctiny.lib". 9 // 10 // v1.0 1/12/2003 J Brown 11 // 12 #include <windows.h> 13 #include <windowsx.h> 14 #include <tchar.h> 15 #include "globals.h" 16 #include "message.h" 17 #include "matrix.h" 18 #include "resource.h" 19 20 //#pragma comment(lib, "libctiny.lib") 21 //#pragma comment(linker, "/OPT:NOWIN98") 22 23 // 24 // Added: Multimonitor support!! 25 // 26 HMONITOR (WINAPI * pfnEnumDisplayMonitors)(HDC, LPCRECT, MONITORENUMPROC, LPARAM); 27 BOOL (WINAPI * pfnGetMonitorInfo)(HMONITOR, LPMONITORINFO); 28 29 // 30 // Callback function for EnumDisplayMonitors API. Use this function 31 // to kickstart a screen-saver window for each monitor in the system 32 // 33 BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, RECT *rcMonitor, LPARAM Param) 34 { 35 HWND hwnd; 36 37 // Create a screensaver on this monitor! 38 hwnd = CreateScreenSaveWnd((HWND)Param, rcMonitor); 39 40 // For some reason windows always places this window at 0,0... 41 // position it ourselves 42 SetWindowPos(hwnd, 0, rcMonitor->left, rcMonitor->top, 0, 0, 43 SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSIZE|SWP_SHOWWINDOW); 44 45 return TRUE; 46 } 47 48 // 49 // Start screen saver! 50 // 51 BOOL ScreenSaver(HWND hwndParent) 52 { 53 HMODULE hUser32; 54 UINT nPreviousState; 55 MSG msg; 56 57 InitScreenSaveClass(hwndParent); 58 59 SystemParametersInfo(SPI_SETSCREENSAVERRUNNING, TRUE, &nPreviousState, 0); 60 61 // Dynamically locate API call from USER32 - not present in all versions 62 hUser32 = GetModuleHandle(_T("USER32.DLL")); 63 pfnEnumDisplayMonitors = (PVOID)GetProcAddress(hUser32, "EnumDisplayMonitors"); 64 65 // If we're running Win2k+ then the API is available...so call it! 66 if(pfnEnumDisplayMonitors && hwndParent == 0) 67 { 68 pfnEnumDisplayMonitors(NULL, NULL, MonitorEnumProc, 0); 69 } 70 // Otherwise simulate by calling enum-proc manually 71 else 72 { 73 RECT rect; 74 75 rect.left = 0; 76 rect.right = GetSystemMetrics(SM_CXSCREEN); 77 rect.top = 0; 78 rect.bottom = GetSystemMetrics(SM_CYSCREEN); 79 80 MonitorEnumProc(NULL, NULL, &rect, (LPARAM)hwndParent); 81 } 82 83 // run message loop to handle all screen-saver windows 84 while(GetMessage(&msg, NULL,0,0)) 85 { 86 TranslateMessage(&msg); 87 DispatchMessage(&msg); 88 } 89 90 SystemParametersInfo(SPI_SETSCREENSAVERRUNNING, FALSE, &nPreviousState, 0); 91 92 return TRUE; 93 } 94 95 // 96 // Look for any options Windows has passed to us: 97 // 98 // -a <hwnd> (set password) 99 // -s (screensave) 100 // -p <hwnd> (preview) 101 // -c <hwnd> (configure) 102 // 103 VOID ParseCommandLine(LPWSTR szCmdLine, UCHAR *chOption, HWND *hwndParent) 104 { 105 UCHAR ch = *szCmdLine++; 106 107 if(ch == '-' || ch == '/') 108 ch = *szCmdLine++; 109 110 if(ch >= 'A' && ch <= 'Z') 111 ch += 'a' - 'A'; //convert to lower case 112 113 *chOption = ch; 114 ch = *szCmdLine++; 115 116 if(ch == ':') 117 ch = *szCmdLine++; 118 119 while(ch == ' ' || ch == '\t') 120 ch = *szCmdLine++; 121 122 if(isdigit(ch)) 123 { 124 ULONG_PTR i = _wtoi(szCmdLine - 1); 125 *hwndParent = (HWND)i; 126 } 127 else 128 *hwndParent = NULL; 129 } 130 131 // 132 // Entrypoint for screen-saver: it's just a normal win32 app! 133 // 134 int CALLBACK wWinMain (HINSTANCE hInst, HINSTANCE hPrev, LPWSTR lpCmdLine, int iCmdShow) 135 { 136 HWND hwndParent; 137 UCHAR chOption; 138 139 // Make sure that only 1 instance runs at a time - 140 // Win98 seems to want us to restart every 5 seconds!! 141 if(FindWindowEx(NULL, NULL, APPNAME, APPNAME)) 142 { 143 return 0; 144 } 145 146 LoadSettings(); 147 148 ParseCommandLine(lpCmdLine, &chOption, &hwndParent); 149 150 switch(chOption) 151 { 152 case 's': return ScreenSaver(NULL); // screen save 153 case 'p': return ScreenSaver(hwndParent); // preview in small window 154 case 'a': return ChangePassword(hwndParent); // ask for password 155 case 'c': return Configure(hwndParent); // configuration dialog 156 default: return Configure(hwndParent); // configuration dialog 157 } 158 159 return 0; 160 } 161