1*c2c66affSColin Finck /*
2*c2c66affSColin Finck * COPYRIGHT: See COPYING in the top level directory
3*c2c66affSColin Finck * PROJECT: ReactOS msgina.dll
4*c2c66affSColin Finck * FILE: dll/win32/msgina/dimmedwindow.cpp
5*c2c66affSColin Finck * PURPOSE: Implementation of ShellDimScreen
6*c2c66affSColin Finck * PROGRAMMER: Mark Jansen
7*c2c66affSColin Finck */
8*c2c66affSColin Finck
9*c2c66affSColin Finck #define COM_NO_WINDOWS_H
10*c2c66affSColin Finck #include "msgina.h"
11*c2c66affSColin Finck #include <wingdi.h>
12*c2c66affSColin Finck #include <atlbase.h>
13*c2c66affSColin Finck #include <atlcom.h>
14*c2c66affSColin Finck #include <pseh/pseh2.h>
15*c2c66affSColin Finck
16*c2c66affSColin Finck CComModule gModule;
17*c2c66affSColin Finck
18*c2c66affSColin Finck // Please note: The INIT_TIMER is a workaround because ReactOS does not redraw the desktop in time,
19*c2c66affSColin Finck // so the start menu is still visible on the dimmed screen.
20*c2c66affSColin Finck #define INIT_TIMER_ID 0x112233
21*c2c66affSColin Finck #define FADE_TIMER_ID 0x12345
22*c2c66affSColin Finck
23*c2c66affSColin Finck class CDimmedWindow :
24*c2c66affSColin Finck public CComObjectRootEx<CComMultiThreadModelNoCS>,
25*c2c66affSColin Finck IUnknown
26*c2c66affSColin Finck {
27*c2c66affSColin Finck private:
28*c2c66affSColin Finck HWND m_hwnd;
29*c2c66affSColin Finck HDC m_hdc;
30*c2c66affSColin Finck HBITMAP m_hbitmap;
31*c2c66affSColin Finck HGDIOBJ m_oldbitmap;
32*c2c66affSColin Finck LONG m_width;
33*c2c66affSColin Finck LONG m_height;
34*c2c66affSColin Finck BITMAPINFO m_bi;
35*c2c66affSColin Finck UCHAR* m_bytes;
36*c2c66affSColin Finck int m_step;
37*c2c66affSColin Finck
38*c2c66affSColin Finck static LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
39*c2c66affSColin Finck
40*c2c66affSColin Finck public:
CDimmedWindow()41*c2c66affSColin Finck CDimmedWindow()
42*c2c66affSColin Finck : m_hwnd(NULL)
43*c2c66affSColin Finck , m_hdc(NULL)
44*c2c66affSColin Finck , m_hbitmap(NULL)
45*c2c66affSColin Finck , m_oldbitmap(NULL)
46*c2c66affSColin Finck , m_width(0)
47*c2c66affSColin Finck , m_height(0)
48*c2c66affSColin Finck , m_bytes(NULL)
49*c2c66affSColin Finck , m_step(0)
50*c2c66affSColin Finck {
51*c2c66affSColin Finck WNDCLASSEXW wndclass = {sizeof(wndclass)};
52*c2c66affSColin Finck wndclass.lpfnWndProc = WndProc;
53*c2c66affSColin Finck wndclass.hInstance = hDllInstance;
54*c2c66affSColin Finck wndclass.hCursor = LoadCursor(0, IDC_ARROW);
55*c2c66affSColin Finck wndclass.lpszClassName = L"DimmedWindowClass";
56*c2c66affSColin Finck
57*c2c66affSColin Finck if (!RegisterClassExW(&wndclass))
58*c2c66affSColin Finck return;
59*c2c66affSColin Finck
60*c2c66affSColin Finck m_width = GetSystemMetrics(SM_CXVIRTUALSCREEN);
61*c2c66affSColin Finck m_height = GetSystemMetrics(SM_CYVIRTUALSCREEN);
62*c2c66affSColin Finck
63*c2c66affSColin Finck memset(&m_bi, 0, sizeof(m_bi));
64*c2c66affSColin Finck m_bi.bmiHeader.biSize = sizeof(m_bi);
65*c2c66affSColin Finck m_bi.bmiHeader.biWidth = m_width;
66*c2c66affSColin Finck m_bi.bmiHeader.biHeight = m_height;
67*c2c66affSColin Finck m_bi.bmiHeader.biPlanes = 1;
68*c2c66affSColin Finck m_bi.bmiHeader.biBitCount = 32;
69*c2c66affSColin Finck m_bi.bmiHeader.biCompression = BI_RGB;
70*c2c66affSColin Finck m_bi.bmiHeader.biSizeImage = m_width * 4 * m_height;
71*c2c66affSColin Finck m_bytes = new UCHAR[m_width * 4 * m_height];
72*c2c66affSColin Finck
73*c2c66affSColin Finck LONG x = GetSystemMetrics(SM_XVIRTUALSCREEN);
74*c2c66affSColin Finck LONG y = GetSystemMetrics(SM_YVIRTUALSCREEN);
75*c2c66affSColin Finck
76*c2c66affSColin Finck m_hwnd = CreateWindowExW(WS_EX_TOPMOST,
77*c2c66affSColin Finck L"DimmedWindowClass",
78*c2c66affSColin Finck NULL,
79*c2c66affSColin Finck WS_POPUP,
80*c2c66affSColin Finck x, y,
81*c2c66affSColin Finck m_width, m_height,
82*c2c66affSColin Finck NULL, NULL,
83*c2c66affSColin Finck hDllInstance,
84*c2c66affSColin Finck (LPVOID)this);
85*c2c66affSColin Finck }
86*c2c66affSColin Finck
~CDimmedWindow()87*c2c66affSColin Finck ~CDimmedWindow()
88*c2c66affSColin Finck {
89*c2c66affSColin Finck if (m_hwnd)
90*c2c66affSColin Finck DestroyWindow(m_hwnd);
91*c2c66affSColin Finck UnregisterClassW(L"DimmedWindowClass", hDllInstance);
92*c2c66affSColin Finck if (m_oldbitmap)
93*c2c66affSColin Finck SelectObject(m_hdc, m_oldbitmap);
94*c2c66affSColin Finck if (m_hbitmap)
95*c2c66affSColin Finck DeleteObject(m_hbitmap);
96*c2c66affSColin Finck if (m_hdc)
97*c2c66affSColin Finck DeleteObject(m_hdc);
98*c2c66affSColin Finck if (m_bytes)
99*c2c66affSColin Finck delete[] m_bytes;
100*c2c66affSColin Finck }
101*c2c66affSColin Finck
102*c2c66affSColin Finck // This is needed so that we do not capture the start menu while it's closing.
WaitForInit()103*c2c66affSColin Finck void WaitForInit()
104*c2c66affSColin Finck {
105*c2c66affSColin Finck MSG msg;
106*c2c66affSColin Finck
107*c2c66affSColin Finck while (IsWindow(m_hwnd) && !IsWindowVisible(m_hwnd))
108*c2c66affSColin Finck {
109*c2c66affSColin Finck while (::PeekMessage(&msg, m_hwnd, 0, 0, PM_REMOVE))
110*c2c66affSColin Finck {
111*c2c66affSColin Finck ::TranslateMessage(&msg);
112*c2c66affSColin Finck ::DispatchMessage(&msg);
113*c2c66affSColin Finck
114*c2c66affSColin Finck if (IsWindowVisible(m_hwnd))
115*c2c66affSColin Finck break;
116*c2c66affSColin Finck }
117*c2c66affSColin Finck }
118*c2c66affSColin Finck }
119*c2c66affSColin Finck
Init()120*c2c66affSColin Finck void Init()
121*c2c66affSColin Finck {
122*c2c66affSColin Finck Capture();
123*c2c66affSColin Finck
124*c2c66affSColin Finck ShowWindow(m_hwnd, SW_SHOW);
125*c2c66affSColin Finck SetForegroundWindow(m_hwnd);
126*c2c66affSColin Finck EnableWindow(m_hwnd, FALSE);
127*c2c66affSColin Finck
128*c2c66affSColin Finck SetTimer(m_hwnd, FADE_TIMER_ID, 200, NULL);
129*c2c66affSColin Finck }
130*c2c66affSColin Finck
Capture()131*c2c66affSColin Finck void Capture()
132*c2c66affSColin Finck {
133*c2c66affSColin Finck HWND desktopWnd = GetDesktopWindow();
134*c2c66affSColin Finck HDC desktopDC = GetDC(desktopWnd);
135*c2c66affSColin Finck
136*c2c66affSColin Finck m_hdc = CreateCompatibleDC(desktopDC);
137*c2c66affSColin Finck
138*c2c66affSColin Finck m_hbitmap = CreateCompatibleBitmap(desktopDC, m_width, m_height);
139*c2c66affSColin Finck m_oldbitmap = SelectObject(m_hdc, m_hbitmap);
140*c2c66affSColin Finck BitBlt(m_hdc, 0, 0, m_width, m_height, desktopDC, 0, 0, SRCCOPY);
141*c2c66affSColin Finck
142*c2c66affSColin Finck ReleaseDC(desktopWnd, desktopDC);
143*c2c66affSColin Finck }
144*c2c66affSColin Finck
Step()145*c2c66affSColin Finck bool Step()
146*c2c66affSColin Finck {
147*c2c66affSColin Finck // Stop after 10 steps
148*c2c66affSColin Finck if (m_step++ > 10 || !m_bytes)
149*c2c66affSColin Finck return false;
150*c2c66affSColin Finck
151*c2c66affSColin Finck int lines = GetDIBits(m_hdc, m_hbitmap, 0, m_height, m_bytes, &m_bi, DIB_RGB_COLORS);
152*c2c66affSColin Finck if (lines)
153*c2c66affSColin Finck {
154*c2c66affSColin Finck for (int xh = 0; xh < m_height; ++xh)
155*c2c66affSColin Finck {
156*c2c66affSColin Finck int h = m_width * 4 * xh;
157*c2c66affSColin Finck for (int w = 0; w < m_width; ++w)
158*c2c66affSColin Finck {
159*c2c66affSColin Finck UCHAR b = m_bytes[(h + w * 4) + 0];
160*c2c66affSColin Finck UCHAR g = m_bytes[(h + w * 4) + 1];
161*c2c66affSColin Finck UCHAR r = m_bytes[(h + w * 4) + 2];
162*c2c66affSColin Finck
163*c2c66affSColin Finck // Standard formula to convert a color.
164*c2c66affSColin Finck int gray = (r * 30 + g * 59 + b * 11) / 100;
165*c2c66affSColin Finck if (gray < 0)
166*c2c66affSColin Finck gray = 0;
167*c2c66affSColin Finck
168*c2c66affSColin Finck // Do not fade too fast.
169*c2c66affSColin Finck r = (r*2 + gray) / 3;
170*c2c66affSColin Finck g = (g*2 + gray) / 3;
171*c2c66affSColin Finck b = (b*2 + gray) / 3;
172*c2c66affSColin Finck
173*c2c66affSColin Finck m_bytes[(h + w * 4) + 0] = b;
174*c2c66affSColin Finck m_bytes[(h + w * 4) + 1] = g;
175*c2c66affSColin Finck m_bytes[(h + w * 4) + 2] = r;
176*c2c66affSColin Finck }
177*c2c66affSColin Finck }
178*c2c66affSColin Finck SetDIBits(m_hdc, m_hbitmap, 0, lines, m_bytes, &m_bi, DIB_RGB_COLORS);
179*c2c66affSColin Finck }
180*c2c66affSColin Finck return true;
181*c2c66affSColin Finck }
182*c2c66affSColin Finck
Blt(HDC hdc)183*c2c66affSColin Finck void Blt(HDC hdc)
184*c2c66affSColin Finck {
185*c2c66affSColin Finck BitBlt(hdc, 0, 0, m_width, m_height, m_hdc, 0, 0, SRCCOPY);
186*c2c66affSColin Finck }
187*c2c66affSColin Finck
Wnd()188*c2c66affSColin Finck HWND Wnd()
189*c2c66affSColin Finck {
190*c2c66affSColin Finck return m_hwnd;
191*c2c66affSColin Finck }
192*c2c66affSColin Finck
193*c2c66affSColin Finck
194*c2c66affSColin Finck BEGIN_COM_MAP(CDimmedWindow)
195*c2c66affSColin Finck COM_INTERFACE_ENTRY_IID(IID_IUnknown, IUnknown)
196*c2c66affSColin Finck END_COM_MAP()
197*c2c66affSColin Finck
198*c2c66affSColin Finck };
199*c2c66affSColin Finck
200*c2c66affSColin Finck
WndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)201*c2c66affSColin Finck LRESULT WINAPI CDimmedWindow::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
202*c2c66affSColin Finck {
203*c2c66affSColin Finck switch (uMsg)
204*c2c66affSColin Finck {
205*c2c66affSColin Finck case WM_NCCREATE:
206*c2c66affSColin Finck {
207*c2c66affSColin Finck LPCREATESTRUCT lpcs = reinterpret_cast<LPCREATESTRUCT>(lParam);
208*c2c66affSColin Finck CDimmedWindow* info = static_cast<CDimmedWindow*>(lpcs->lpCreateParams);
209*c2c66affSColin Finck SetWindowLongPtrW(hWnd, GWLP_USERDATA, (LONG_PTR)info);
210*c2c66affSColin Finck SetTimer(hWnd, INIT_TIMER_ID, 50, NULL);
211*c2c66affSColin Finck break;
212*c2c66affSColin Finck }
213*c2c66affSColin Finck
214*c2c66affSColin Finck case WM_PAINT:
215*c2c66affSColin Finck {
216*c2c66affSColin Finck CDimmedWindow* info = reinterpret_cast<CDimmedWindow*>(GetWindowLongPtrW(hWnd, GWLP_USERDATA));
217*c2c66affSColin Finck if (info)
218*c2c66affSColin Finck {
219*c2c66affSColin Finck PAINTSTRUCT ps;
220*c2c66affSColin Finck BeginPaint(hWnd, &ps);
221*c2c66affSColin Finck info->Blt(ps.hdc);
222*c2c66affSColin Finck EndPaint(hWnd, &ps);
223*c2c66affSColin Finck }
224*c2c66affSColin Finck return 0;
225*c2c66affSColin Finck }
226*c2c66affSColin Finck
227*c2c66affSColin Finck case WM_TIMER:
228*c2c66affSColin Finck {
229*c2c66affSColin Finck if (wParam == INIT_TIMER_ID)
230*c2c66affSColin Finck {
231*c2c66affSColin Finck CDimmedWindow* info = reinterpret_cast<CDimmedWindow*>(GetWindowLongPtrW(hWnd, GWLP_USERDATA));
232*c2c66affSColin Finck KillTimer(hWnd, INIT_TIMER_ID);
233*c2c66affSColin Finck info->Init();
234*c2c66affSColin Finck }
235*c2c66affSColin Finck else if (wParam == FADE_TIMER_ID)
236*c2c66affSColin Finck {
237*c2c66affSColin Finck CDimmedWindow* info = reinterpret_cast<CDimmedWindow*>(GetWindowLongPtrW(hWnd, GWLP_USERDATA));
238*c2c66affSColin Finck if (info && info->Step())
239*c2c66affSColin Finck InvalidateRect(hWnd, NULL, TRUE);
240*c2c66affSColin Finck else
241*c2c66affSColin Finck KillTimer(hWnd, FADE_TIMER_ID);
242*c2c66affSColin Finck }
243*c2c66affSColin Finck return 0;
244*c2c66affSColin Finck }
245*c2c66affSColin Finck
246*c2c66affSColin Finck default:
247*c2c66affSColin Finck break;
248*c2c66affSColin Finck }
249*c2c66affSColin Finck
250*c2c66affSColin Finck return DefWindowProc(hWnd, uMsg, wParam, lParam);
251*c2c66affSColin Finck }
252*c2c66affSColin Finck
253*c2c66affSColin Finck
254*c2c66affSColin Finck extern "C"
255*c2c66affSColin Finck HRESULT WINAPI
ShellDimScreen(void ** pUnknown,HWND * hWindow)256*c2c66affSColin Finck ShellDimScreen(void** pUnknown, HWND* hWindow)
257*c2c66affSColin Finck {
258*c2c66affSColin Finck CComObject<CDimmedWindow> *pWindow;
259*c2c66affSColin Finck HRESULT hr = CComObject<CDimmedWindow>::CreateInstance(&pWindow);
260*c2c66affSColin Finck ULONG refcount;
261*c2c66affSColin Finck
262*c2c66affSColin Finck pWindow->WaitForInit();
263*c2c66affSColin Finck
264*c2c66affSColin Finck if (!IsWindow(pWindow->Wnd()))
265*c2c66affSColin Finck {
266*c2c66affSColin Finck refcount = pWindow->AddRef();
267*c2c66affSColin Finck while (refcount)
268*c2c66affSColin Finck refcount = pWindow->Release();
269*c2c66affSColin Finck
270*c2c66affSColin Finck return E_FAIL;
271*c2c66affSColin Finck }
272*c2c66affSColin Finck
273*c2c66affSColin Finck _SEH2_TRY
274*c2c66affSColin Finck {
275*c2c66affSColin Finck hr = pWindow->QueryInterface(IID_IUnknown, pUnknown);
276*c2c66affSColin Finck *hWindow = pWindow->Wnd();
277*c2c66affSColin Finck hr = S_OK;
278*c2c66affSColin Finck }
279*c2c66affSColin Finck _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
280*c2c66affSColin Finck {
281*c2c66affSColin Finck hr = E_INVALIDARG;
282*c2c66affSColin Finck refcount = pWindow->AddRef();
283*c2c66affSColin Finck while (refcount)
284*c2c66affSColin Finck refcount = pWindow->Release();
285*c2c66affSColin Finck }
286*c2c66affSColin Finck _SEH2_END
287*c2c66affSColin Finck
288*c2c66affSColin Finck return hr;
289*c2c66affSColin Finck }
290