Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS msgina.dll * FILE: dll/win32/msgina/dimmedwindow.cpp * PURPOSE: Implementation of ShellDimScreen * PROGRAMMER: Mark Jansen */
#define COM_NO_WINDOWS_H#include "msgina.h"#include <wingdi.h>#include <atlbase.h>#include <atlcom.h>#include <pseh/pseh2.h>
CComModule gModule;
// Please note: The INIT_TIMER is a workaround because ReactOS does not redraw the desktop in time,// so the start menu is still visible on the dimmed screen.#define INIT_TIMER_ID 0x112233#define FADE_TIMER_ID 0x12345
class CDimmedWindow : public CComObjectRootEx<CComMultiThreadModelNoCS>, IUnknown{private: HWND m_hwnd; HDC m_hdc; HBITMAP m_hbitmap; HGDIOBJ m_oldbitmap; LONG m_width; LONG m_height; BITMAPINFO m_bi; UCHAR* m_bytes; int m_step;
static LRESULT WINAPI WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
public: CDimmedWindow() : m_hwnd(NULL) , m_hdc(NULL) , m_hbitmap(NULL) , m_oldbitmap(NULL) , m_width(0) , m_height(0) , m_bytes(NULL) , m_step(0) { WNDCLASSEXW wndclass = {sizeof(wndclass)}; wndclass.lpfnWndProc = WndProc; wndclass.hInstance = hDllInstance; wndclass.hCursor = LoadCursor(0, IDC_ARROW); wndclass.lpszClassName = L"DimmedWindowClass";
if (!RegisterClassExW(&wndclass)) return;
m_width = GetSystemMetrics(SM_CXVIRTUALSCREEN); m_height = GetSystemMetrics(SM_CYVIRTUALSCREEN);
memset(&m_bi, 0, sizeof(m_bi)); m_bi.bmiHeader.biSize = sizeof(m_bi); m_bi.bmiHeader.biWidth = m_width; m_bi.bmiHeader.biHeight = m_height; m_bi.bmiHeader.biPlanes = 1; m_bi.bmiHeader.biBitCount = 32; m_bi.bmiHeader.biCompression = BI_RGB; m_bi.bmiHeader.biSizeImage = m_width * 4 * m_height; m_bytes = new UCHAR[m_width * 4 * m_height];
LONG x = GetSystemMetrics(SM_XVIRTUALSCREEN); LONG y = GetSystemMetrics(SM_YVIRTUALSCREEN);
m_hwnd = CreateWindowExW(WS_EX_TOPMOST, L"DimmedWindowClass", NULL, WS_POPUP, x, y, m_width, m_height, NULL, NULL, hDllInstance, (LPVOID)this); }
~CDimmedWindow() { if (m_hwnd) DestroyWindow(m_hwnd); UnregisterClassW(L"DimmedWindowClass", hDllInstance); if (m_oldbitmap) SelectObject(m_hdc, m_oldbitmap); if (m_hbitmap) DeleteObject(m_hbitmap); if (m_hdc) DeleteObject(m_hdc); if (m_bytes) delete[] m_bytes; }
// This is needed so that we do not capture the start menu while it's closing. void WaitForInit() { MSG msg;
while (IsWindow(m_hwnd) && !IsWindowVisible(m_hwnd)) { while (::PeekMessage(&msg, m_hwnd, 0, 0, PM_REMOVE)) { ::TranslateMessage(&msg); ::DispatchMessage(&msg);
if (IsWindowVisible(m_hwnd)) break; } } }
void Init() { Capture();
ShowWindow(m_hwnd, SW_SHOW); SetForegroundWindow(m_hwnd); EnableWindow(m_hwnd, FALSE);
SetTimer(m_hwnd, FADE_TIMER_ID, 200, NULL); }
void Capture() { HWND desktopWnd = GetDesktopWindow(); HDC desktopDC = GetDC(desktopWnd);
m_hdc = CreateCompatibleDC(desktopDC);
m_hbitmap = CreateCompatibleBitmap(desktopDC, m_width, m_height); m_oldbitmap = SelectObject(m_hdc, m_hbitmap); BitBlt(m_hdc, 0, 0, m_width, m_height, desktopDC, 0, 0, SRCCOPY);
ReleaseDC(desktopWnd, desktopDC); }
bool Step() { // Stop after 10 steps if (m_step++ > 10 || !m_bytes) return false;
int lines = GetDIBits(m_hdc, m_hbitmap, 0, m_height, m_bytes, &m_bi, DIB_RGB_COLORS); if (lines) { for (int xh = 0; xh < m_height; ++xh) { int h = m_width * 4 * xh; for (int w = 0; w < m_width; ++w) { UCHAR b = m_bytes[(h + w * 4) + 0]; UCHAR g = m_bytes[(h + w * 4) + 1]; UCHAR r = m_bytes[(h + w * 4) + 2];
// Standard formula to convert a color. int gray = (r * 30 + g * 59 + b * 11) / 100; if (gray < 0) gray = 0;
// Do not fade too fast. r = (r*2 + gray) / 3; g = (g*2 + gray) / 3; b = (b*2 + gray) / 3;
m_bytes[(h + w * 4) + 0] = b; m_bytes[(h + w * 4) + 1] = g; m_bytes[(h + w * 4) + 2] = r; } } SetDIBits(m_hdc, m_hbitmap, 0, lines, m_bytes, &m_bi, DIB_RGB_COLORS); } return true; }
void Blt(HDC hdc) { BitBlt(hdc, 0, 0, m_width, m_height, m_hdc, 0, 0, SRCCOPY); }
HWND Wnd() { return m_hwnd; }
BEGIN_COM_MAP(CDimmedWindow) COM_INTERFACE_ENTRY_IID(IID_IUnknown, IUnknown) END_COM_MAP()
};
LRESULT WINAPI CDimmedWindow::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){ switch (uMsg) { case WM_NCCREATE: { LPCREATESTRUCT lpcs = reinterpret_cast<LPCREATESTRUCT>(lParam); CDimmedWindow* info = static_cast<CDimmedWindow*>(lpcs->lpCreateParams); SetWindowLongPtrW(hWnd, GWLP_USERDATA, (LONG_PTR)info); SetTimer(hWnd, INIT_TIMER_ID, 50, NULL); break; }
case WM_PAINT: { CDimmedWindow* info = reinterpret_cast<CDimmedWindow*>(GetWindowLongPtrW(hWnd, GWLP_USERDATA)); if (info) { PAINTSTRUCT ps; BeginPaint(hWnd, &ps); info->Blt(ps.hdc); EndPaint(hWnd, &ps); } return 0; }
case WM_TIMER: { if (wParam == INIT_TIMER_ID) { CDimmedWindow* info = reinterpret_cast<CDimmedWindow*>(GetWindowLongPtrW(hWnd, GWLP_USERDATA)); KillTimer(hWnd, INIT_TIMER_ID); info->Init(); } else if (wParam == FADE_TIMER_ID) { CDimmedWindow* info = reinterpret_cast<CDimmedWindow*>(GetWindowLongPtrW(hWnd, GWLP_USERDATA)); if (info && info->Step()) InvalidateRect(hWnd, NULL, TRUE); else KillTimer(hWnd, FADE_TIMER_ID); } return 0; }
default: break; }
return DefWindowProc(hWnd, uMsg, wParam, lParam);}
extern "C"HRESULT WINAPIShellDimScreen(void** pUnknown, HWND* hWindow){ CComObject<CDimmedWindow> *pWindow; HRESULT hr = CComObject<CDimmedWindow>::CreateInstance(&pWindow); ULONG refcount;
pWindow->WaitForInit();
if (!IsWindow(pWindow->Wnd())) { refcount = pWindow->AddRef(); while (refcount) refcount = pWindow->Release();
return E_FAIL; }
_SEH2_TRY { hr = pWindow->QueryInterface(IID_IUnknown, pUnknown); *hWindow = pWindow->Wnd(); hr = S_OK; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { hr = E_INVALIDARG; refcount = pWindow->AddRef(); while (refcount) refcount = pWindow->Release(); } _SEH2_END
return hr;}