[SDK:SCRNSAVE]

- Add support for specifying a parent window handle for the screensaver configuration dialog, adapted from patch by Timo Kreuzer, see CORE-5718.
- Fix failure return values from the helper functions.
- Add TranslateMessage call in the message pump.
- Get the correct left/top coordinates for the screensaver, being multi-screen aware.
- Use Win-compatible window names & styles for the screensaver preview dialog & screensaver window, compatible MS' scrnsave.lib.

svn path=/trunk/; revision=68776
This commit is contained in:
Hermès Bélusca-Maïto 2015-08-20 19:44:13 +00:00
parent 3e071ece57
commit fa66a17890

View file

@ -2,7 +2,8 @@
* PROJECT: ReactOS Screen Saver Library * PROJECT: ReactOS Screen Saver Library
* LICENSE: GPL v2 or any later version * LICENSE: GPL v2 or any later version
* FILE: lib/sdk/scrnsave/scrnsave.c * FILE: lib/sdk/scrnsave/scrnsave.c
* PURPOSE: Library for writing screen savers, compatible with MS' scrnsave.lib * PURPOSE: Library for writing screen savers, compatible with
* MS' scrnsave.lib without Win9x support.
* PROGRAMMERS: Anders Norlander <anorland@hem2.passagen.se> * PROGRAMMERS: Anders Norlander <anorland@hem2.passagen.se>
* Colin Finck <mail@colinfinck.de> * Colin Finck <mail@colinfinck.de>
*/ */
@ -38,7 +39,7 @@ static int ISSPACE(TCHAR c)
return (c == ' ' || c == '\t'); return (c == ' ' || c == '\t');
} }
#define ISNUM(c) ((c) >= '0' && c <= '9') #define ISNUM(c) ((c) >= '0' && (c) <= '9')
static ULONG_PTR _toulptr(const TCHAR *s) static ULONG_PTR _toulptr(const TCHAR *s)
{ {
@ -78,9 +79,11 @@ static LRESULT WINAPI SysScreenSaverProc(HWND hWnd, UINT uMsg, WPARAM wParam, LP
{ {
switch (wParam) switch (wParam)
{ {
case SC_CLOSE: case SC_CLOSE: // - Closing the screen saver, or...
case SC_SCREENSAVE: case SC_NEXTWINDOW: // - Switching to
return FALSE; case SC_PREVWINDOW: // different windows, or...
case SC_SCREENSAVE: // - Starting another screen saver:
return FALSE; // Fail it!
} }
} }
break; break;
@ -102,7 +105,7 @@ LRESULT WINAPI DefScreenSaverProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lP
case WM_ACTIVATEAPP: case WM_ACTIVATEAPP:
if (!wParam) if (!wParam)
{ {
// wParam is FALSE, so the screensaver is losing the focus. // wParam is FALSE, so the screen saver is losing the focus.
PostMessage(hWnd, WM_CLOSE, 0, 0); PostMessage(hWnd, WM_CLOSE, 0, 0);
} }
break; break;
@ -111,6 +114,8 @@ LRESULT WINAPI DefScreenSaverProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lP
{ {
POINT pt; POINT pt;
GetCursorPos(&pt); GetCursorPos(&pt);
// TODO: Implement mouse move threshold. See:
// http://svn.reactos.org/svn/reactos/trunk/rosapps/applications/screensavers/starfield/screensaver.c?r1=67455&r2=67454&pathrev=67455
if (pt.x == pt_orig.x && pt.y == pt_orig.y) if (pt.x == pt_orig.x && pt.y == pt_orig.y)
break; break;
@ -118,11 +123,14 @@ LRESULT WINAPI DefScreenSaverProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lP
} }
case WM_LBUTTONDOWN: case WM_LBUTTONDOWN:
case WM_RBUTTONDOWN:
case WM_MBUTTONDOWN: case WM_MBUTTONDOWN:
case WM_RBUTTONDOWN:
case WM_XBUTTONDOWN:
case WM_KEYDOWN: case WM_KEYDOWN:
case WM_KEYUP: case WM_KEYUP:
// Send a WM_CLOSE to close the screen saver (allows the screensaver author to do clean-up tasks) case WM_SYSKEYDOWN:
// Send a WM_CLOSE to close the screen saver (allows
// the screen saver to perform clean-up tasks)
PostMessage(hWnd, WM_CLOSE, 0, 0); PostMessage(hWnd, WM_CLOSE, 0, 0);
break; break;
@ -137,60 +145,81 @@ LRESULT WINAPI DefScreenSaverProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lP
// Registers the screen saver window class // Registers the screen saver window class
static BOOL RegisterScreenSaverClass(void) static BOOL RegisterScreenSaverClass(void)
{ {
WNDCLASS cls = {0,}; WNDCLASS cls;
cls.hIcon = LoadIcon(hMainInstance, MAKEINTATOM(ID_APP)); cls.hCursor = NULL;
cls.hIcon = LoadIcon(hMainInstance, MAKEINTATOM(ID_APP));
cls.lpszMenuName = NULL;
cls.lpszClassName = CLASS_SCRNSAVE; cls.lpszClassName = CLASS_SCRNSAVE;
cls.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); cls.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
cls.hInstance = hMainInstance; cls.hInstance = hMainInstance;
cls.style = CS_VREDRAW | CS_HREDRAW | CS_SAVEBITS | CS_PARENTDC; cls.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS | CS_SAVEBITS | CS_PARENTDC;
cls.lpfnWndProc = SysScreenSaverProc; cls.lpfnWndProc = SysScreenSaverProc;
cls.cbWndExtra = 0;
cls.cbClsExtra = 0;
return RegisterClass(&cls) != 0; return (RegisterClass(&cls) != 0);
} }
static void LaunchConfig(void) static int LaunchConfig(HWND hParent)
{ {
// Only show the dialog if the RegisterDialogClasses function succeeded. // Only show the dialog if the RegisterDialogClasses function succeeded.
// This is the same behaviour as MS' scrnsave.lib. // This is the same behaviour as MS' scrnsave.lib.
if( RegisterDialogClasses(hMainInstance) ) if (!RegisterDialogClasses(hMainInstance))
DialogBox(hMainInstance, MAKEINTRESOURCE(DLG_SCRNSAVECONFIGURE), GetForegroundWindow(), (DLGPROC) ScreenSaverConfigureDialog); return -1;
return DialogBox(hMainInstance, MAKEINTRESOURCE(DLG_SCRNSAVECONFIGURE),
hParent, (DLGPROC)ScreenSaverConfigureDialog);
} }
static int LaunchScreenSaver(HWND hParent) static int LaunchScreenSaver(HWND hParent)
{ {
UINT style; LPCTSTR lpWindowName;
UINT style, exstyle;
RECT rc; RECT rc;
MSG msg; MSG msg;
if (!RegisterScreenSaverClass()) if (!RegisterScreenSaverClass())
{ {
MessageBox(NULL, TEXT("RegisterClass() failed"), NULL, MB_ICONHAND); MessageBox(NULL, TEXT("RegisterClass() failed"), NULL, MB_ICONHAND);
return 1; return -1;
} }
// A slightly different approach needs to be used when displaying in a preview window // A slightly different approach needs to be used when displaying in a preview window
if (hParent) if (hParent)
{ {
style = WS_CHILD; fChildPreview = TRUE;
lpWindowName = TEXT("Preview");
style = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN;
exstyle = 0;
GetClientRect(hParent, &rc); GetClientRect(hParent, &rc);
rc.left = 0;
rc.top = 0;
} }
else else
{ {
style = WS_POPUP; fChildPreview = FALSE;
rc.right = GetSystemMetrics(SM_CXVIRTUALSCREEN); lpWindowName = TEXT("Screen Saver");
style = WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
exstyle = WS_EX_TOOLWINDOW | WS_EX_TOPMOST;
// Get the left & top side coordinates of the virtual screen
rc.left = GetSystemMetrics(SM_XVIRTUALSCREEN);
rc.top = GetSystemMetrics(SM_YVIRTUALSCREEN);
// Get the width and height of the virtual screen
rc.right = GetSystemMetrics(SM_CXVIRTUALSCREEN);
rc.bottom = GetSystemMetrics(SM_CYVIRTUALSCREEN); rc.bottom = GetSystemMetrics(SM_CYVIRTUALSCREEN);
style |= WS_VISIBLE;
} }
// Create the main screen saver window // Create the main screen saver window
hMainWindow = CreateWindowEx(hParent ? 0 : WS_EX_TOPMOST, CLASS_SCRNSAVE, hMainWindow = CreateWindowEx(exstyle, CLASS_SCRNSAVE, lpWindowName, style,
TEXT("SCREENSAVER"), style, rc.left, rc.top, rc.right, rc.bottom,
0, 0, rc.right, rc.bottom, hParent, NULL, hParent, NULL, hMainInstance, NULL);
hMainInstance, NULL); if (!hMainWindow)
return -1;
if(!hMainWindow)
return 1;
// Display window and start pumping messages // Display window and start pumping messages
ShowWindow(hMainWindow, SW_SHOW); ShowWindow(hMainWindow, SW_SHOW);
@ -198,7 +227,10 @@ static int LaunchScreenSaver(HWND hParent)
SetCursor(NULL); SetCursor(NULL);
while (GetMessage(&msg, NULL, 0, 0)) while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg); DispatchMessage(&msg);
}
return msg.wParam; return msg.wParam;
} }
@ -208,12 +240,16 @@ int APIENTRY _tWinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPTSTR CmdLine, int
{ {
LPTSTR p; LPTSTR p;
UNREFERENCED_PARAMETER(nCmdShow); UNREFERENCED_PARAMETER(nCmdShow);
UNREFERENCED_PARAMETER(hPrevInst); UNREFERENCED_PARAMETER(hPrevInst);
hMainInstance = hInst; hMainInstance = hInst;
// Parse the arguments // Parse the arguments:
// -a <hwnd> (Change the password; only for Win9x, unused on WinNT)
// -s (Run the screensaver)
// -p <hwnd> (Preview)
// -c <hwnd> (Configure)
for (p = CmdLine; *p; p++) for (p = CmdLine; *p; p++)
{ {
switch (*p) switch (*p)
@ -226,23 +262,34 @@ int APIENTRY _tWinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPTSTR CmdLine, int
case 'P': case 'P':
case 'p': case 'p':
{ {
// Start the screen saver in preview mode
HWND hParent; HWND hParent;
fChildPreview = TRUE;
while (ISSPACE(*++p)); while (ISSPACE(*++p));
hParent = (HWND) _toulptr(p); hParent = (HWND)_toulptr(p);
// Start the screen saver in preview mode
if (hParent && IsWindow(hParent)) if (hParent && IsWindow(hParent))
return LaunchScreenSaver(hParent); return LaunchScreenSaver(hParent);
else
return -1;
} }
return 0;
case 'C': case 'C':
case 'c': case 'c':
{
HWND hParent;
if (p[1] == ':')
hParent = (HWND)_toulptr(p + 2);
else
hParent = GetForegroundWindow();
// Display the configuration dialog // Display the configuration dialog
LaunchConfig(); if (hParent && IsWindow(hParent))
return 0; return LaunchConfig(hParent);
else
return -1;
}
case '-': case '-':
case '/': case '/':
@ -252,7 +299,5 @@ int APIENTRY _tWinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPTSTR CmdLine, int
} }
} }
LaunchConfig(); return LaunchConfig(NULL);
return 0;
} }