1 /*
2  *  Copyright 2003 J Brown
3  *  Copyright 2006 Eric Kohl
4  *  Copyright 2007 Marc Piulachs (marc.piulachs@codexchange.net)
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License along
17  *  with this program; if not, write to the Free Software Foundation, Inc.,
18  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19  */
20 
21 #include <stdlib.h>
22 #include <windef.h>
23 #include <winbase.h>
24 #include <wingdi.h>
25 #include <winuser.h>
26 #include <scrnsave.h>
27 
28 #include "resource.h"
29 
30 #define RANDOM(min, max) ((rand() % (int)(((max)+1) - (min))) + (min))
31 
32 #define APP_TIMER             1
33 #define APP_TIMER_INTERVAL    10000
34 
35 static
36 HBITMAP
37 GetScreenSaverBitmap(VOID)
38 {
39     OSVERSIONINFOEX osvi = {0};
40     osvi.dwOSVersionInfoSize = sizeof(osvi);
41     GetVersionEx((POSVERSIONINFO)&osvi);
42 
43     return LoadImageW(GetModuleHandle(NULL),
44                       osvi.wProductType == VER_NT_WORKSTATION ?
45                           MAKEINTRESOURCEW(IDB_WORKSTATION) : MAKEINTRESOURCEW(IDB_SERVER),
46                       IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
47 }
48 
49 LRESULT
50 CALLBACK
51 ScreenSaverProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
52 {
53     static HBITMAP bitmap;
54 
55     switch (uMsg)
56     {
57         case WM_CREATE:
58         {
59             bitmap = GetScreenSaverBitmap();
60             if (bitmap == NULL)
61             {
62                 /* Extremely unlikely, message not localized. */
63                 MessageBoxW(hWnd,
64                             L"Fatal Error: Could not load bitmap",
65                             L"Error",
66                             MB_OK | MB_ICONEXCLAMATION);
67             }
68 
69             SetTimer(hWnd, APP_TIMER, APP_TIMER_INTERVAL, NULL);
70             break;
71         }
72         case WM_PAINT:
73         {
74             BITMAP bm;
75             PAINTSTRUCT ps;
76             HDC hdc;
77             HDC hdcMem;
78             HBITMAP hbmOld;
79             RECT rect;
80 
81             hdc = BeginPaint(hWnd, &ps);
82             hdcMem = CreateCompatibleDC(hdc);
83             hbmOld = SelectObject(hdcMem, bitmap);
84             GetObjectW(bitmap, sizeof(bm), &bm);
85 
86             GetClientRect(hWnd, &rect);
87             if (rect.right < bm.bmWidth || rect.bottom < bm.bmHeight)
88             {
89                 StretchBlt(hdc, RANDOM(0, rect.right - (bm.bmWidth / 5)),
90                            RANDOM(0, rect.bottom - (bm.bmHeight / 5)),
91                            bm.bmWidth / 5, bm.bmHeight / 5, hdcMem, 0, 0,
92                            bm.bmWidth, bm.bmHeight, SRCCOPY);
93             }
94             else
95             {
96                 BitBlt(hdc, RANDOM(0, rect.right - bm.bmWidth),
97                     RANDOM(0, rect.bottom - bm.bmHeight),
98                     bm.bmWidth, bm.bmHeight, hdcMem, 0, 0, SRCCOPY);
99             }
100 
101             SelectObject(hdcMem, hbmOld);
102             DeleteDC(hdcMem);
103             EndPaint(hWnd, &ps);
104             break;
105         }
106         case WM_TIMER:
107         {
108             InvalidateRect(hWnd, NULL, TRUE);
109             break;
110         }
111         case WM_DESTROY:
112         {
113             KillTimer(hWnd, APP_TIMER);
114             DeleteObject(bitmap);
115             PostQuitMessage(0);
116             break;
117         }
118         default:
119         {
120             /* Pass window messages to the default screensaver window procedure */
121             return DefScreenSaverProc(hWnd, uMsg, wParam, lParam);
122         }
123     }
124 
125     return 0;
126 }
127 
128 BOOL
129 WINAPI
130 ScreenSaverConfigureDialog(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
131 {
132     return FALSE;
133 }
134 
135 /* This function is only called once before opening the configuration dialog.
136  * Use it to show a message that no configuration is necessary and return FALSE to indicate that no configuration dialog shall be opened.
137  */
138 BOOL
139 WINAPI
140 RegisterDialogClasses(HANDLE hInst)
141 {
142     WCHAR szMessage[256];
143     WCHAR szTitle[25];
144 
145     LoadStringW(hInst, IDS_TEXT, szMessage, _countof(szMessage));
146     LoadStringW(hInst, IDS_DESCRIPTION, szTitle, _countof(szTitle));
147 
148     MessageBoxW(NULL, szMessage, szTitle, MB_OK | MB_ICONEXCLAMATION);
149 
150     return FALSE;
151 }
152