2 * PROJECT: ReactOS Screen Saver Library
3 * LICENSE: GPL v2 or any later version
4 * FILE: lib/sdk/scrnsave/scrnsave.c
5 * PURPOSE: Library for writing screen savers, compatible with
6 * MS' scrnsave.lib without Win9x support.
7 * PROGRAMMERS: Anders Norlander <anorland@hem2.passagen.se>
8 * Colin Finck <mail@colinfinck.de>
19 // Screen Saver window class
20 #define CLASS_SCRNSAVE TEXT("WindowsScreenSaverClass")
23 HWND hMainWindow
= NULL
;
24 BOOL fChildPreview
= FALSE
;
25 HINSTANCE hMainInstance
;
26 TCHAR szName
[TITLEBARNAMELEN
];
27 TCHAR szAppName
[APPNAMEBUFFERLEN
];
28 TCHAR szIniFile
[MAXFILELEN
];
29 TCHAR szScreenSaver
[22];
30 TCHAR szHelpFile
[MAXFILELEN
];
31 TCHAR szNoHelpMemory
[BUFFLEN
];
34 // Local house keeping
37 static int ISSPACE(TCHAR c
)
39 return (c
== ' ' || c
== '\t');
42 #define ISNUM(c) ((c) >= '0' && (c) <= '9')
44 static ULONG_PTR
_toulptr(const TCHAR
*s
)
57 for (n
= 1; p
>= s
; p
--, n
*= 10)
58 res
+= (*p
- '0') * n
;
63 // This function takes care of *must* do tasks, like terminating screen saver
64 static LRESULT WINAPI
SysScreenSaverProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
69 // Mouse is not supposed to move from this position
70 GetCursorPos(&pt_orig
);
82 case SC_CLOSE
: // - Closing the screen saver, or...
83 case SC_NEXTWINDOW
: // - Switching to
84 case SC_PREVWINDOW
: // different windows, or...
85 case SC_SCREENSAVE
: // - Starting another screen saver:
86 return FALSE
; // Fail it!
92 return ScreenSaverProc(hWnd
, uMsg
, wParam
, lParam
);
95 LRESULT WINAPI
DefScreenSaverProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
97 // Don't do any special processing when in preview mode
99 return DefWindowProc(hWnd
, uMsg
, wParam
, lParam
);
108 // wParam is FALSE, so the screen saver is losing the focus.
109 PostMessage(hWnd
, WM_CLOSE
, 0, 0);
117 // TODO: Implement mouse move threshold. See:
118 // http://svn.reactos.org/svn/reactos/trunk/rosapps/applications/screensavers/starfield/screensaver.c?r1=67455&r2=67454&pathrev=67455
119 if (pt
.x
== pt_orig
.x
&& pt
.y
== pt_orig
.y
)
132 // Send a WM_CLOSE to close the screen saver (allows
133 // the screen saver to perform clean-up tasks)
134 PostMessage(hWnd
, WM_CLOSE
, 0, 0);
142 return DefWindowProc(hWnd
, uMsg
, wParam
, lParam
);
145 // Registers the screen saver window class
146 static BOOL
RegisterScreenSaverClass(void)
151 cls
.hIcon
= LoadIcon(hMainInstance
, MAKEINTATOM(ID_APP
));
152 cls
.lpszMenuName
= NULL
;
153 cls
.lpszClassName
= CLASS_SCRNSAVE
;
154 cls
.hbrBackground
= (HBRUSH
)GetStockObject(BLACK_BRUSH
);
155 cls
.hInstance
= hMainInstance
;
156 cls
.style
= CS_VREDRAW
| CS_HREDRAW
| CS_DBLCLKS
| CS_SAVEBITS
| CS_PARENTDC
;
157 cls
.lpfnWndProc
= SysScreenSaverProc
;
161 return (RegisterClass(&cls
) != 0);
164 static int LaunchConfig(HWND hParent
)
166 // Only show the dialog if the RegisterDialogClasses function succeeded.
167 // This is the same behaviour as MS' scrnsave.lib.
168 if (!RegisterDialogClasses(hMainInstance
))
171 return DialogBox(hMainInstance
, MAKEINTRESOURCE(DLG_SCRNSAVECONFIGURE
),
172 hParent
, (DLGPROC
)ScreenSaverConfigureDialog
);
175 static int LaunchScreenSaver(HWND hParent
)
177 LPCTSTR lpWindowName
;
182 if (!RegisterScreenSaverClass())
184 MessageBox(NULL
, TEXT("RegisterClass() failed"), NULL
, MB_ICONHAND
);
188 // A slightly different approach needs to be used when displaying in a preview window
191 fChildPreview
= TRUE
;
192 lpWindowName
= TEXT("Preview");
194 style
= WS_CHILD
| WS_VISIBLE
| WS_CLIPCHILDREN
;
197 GetClientRect(hParent
, &rc
);
203 fChildPreview
= FALSE
;
204 lpWindowName
= TEXT("Screen Saver");
206 style
= WS_POPUP
| WS_VISIBLE
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
;
207 exstyle
= WS_EX_TOOLWINDOW
| WS_EX_TOPMOST
;
209 // Get the left & top side coordinates of the virtual screen
210 rc
.left
= GetSystemMetrics(SM_XVIRTUALSCREEN
);
211 rc
.top
= GetSystemMetrics(SM_YVIRTUALSCREEN
);
212 // Get the width and height of the virtual screen
213 rc
.right
= GetSystemMetrics(SM_CXVIRTUALSCREEN
);
214 rc
.bottom
= GetSystemMetrics(SM_CYVIRTUALSCREEN
);
217 // Create the main screen saver window
218 hMainWindow
= CreateWindowEx(exstyle
, CLASS_SCRNSAVE
, lpWindowName
, style
,
219 rc
.left
, rc
.top
, rc
.right
, rc
.bottom
,
220 hParent
, NULL
, hMainInstance
, NULL
);
224 // Display window and start pumping messages
225 ShowWindow(hMainWindow
, SW_SHOW
);
229 while (GetMessage(&msg
, NULL
, 0, 0))
231 TranslateMessage(&msg
);
232 DispatchMessage(&msg
);
238 // Screen Saver entry point
239 int APIENTRY
_tWinMain(HINSTANCE hInst
, HINSTANCE hPrevInst
, LPTSTR CmdLine
, int nCmdShow
)
243 UNREFERENCED_PARAMETER(nCmdShow
);
244 UNREFERENCED_PARAMETER(hPrevInst
);
246 hMainInstance
= hInst
;
248 // Parse the arguments:
249 // -a <hwnd> (Change the password; only for Win9x, unused on WinNT)
250 // -s (Run the screensaver)
251 // -p <hwnd> (Preview)
252 // -c <hwnd> (Configure)
253 for (p
= CmdLine
; *p
; p
++)
259 // Start the screen saver
260 return LaunchScreenSaver(NULL
);
267 while (ISSPACE(*++p
));
268 hParent
= (HWND
)_toulptr(p
);
270 // Start the screen saver in preview mode
271 if (hParent
&& IsWindow(hParent
))
272 return LaunchScreenSaver(hParent
);
283 hParent
= (HWND
)_toulptr(p
+ 2);
285 hParent
= GetForegroundWindow();
287 // Display the configuration dialog
288 if (hParent
&& IsWindow(hParent
))
289 return LaunchConfig(hParent
);
302 return LaunchConfig(NULL
);