Index: dll/win32/shell32/dialogs/dialogs.cpp =================================================================== --- dll/win32/shell32/dialogs/dialogs.cpp (revision 71643) +++ dll/win32/shell32/dialogs/dialogs.cpp (working copy) @@ -713,6 +713,185 @@ } + +class FadeHandler +{ +private: + HWND m_hwnd; + HWND m_owner; + 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 Proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + +public: + FadeHandler(HWND owner) + : m_hwnd(NULL) + , m_owner(owner) + , 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 = Proc; + wndclass.hInstance = shell32_hInstance; + wndclass.hCursor = LoadCursorW(0, IDC_ARROW); + wndclass.lpszClassName = L"ReactOS_Fading_BG"; + + if (!RegisterClassExW(&wndclass)) + return; + + + HWND desktopWnd = GetDesktopWindow(); + HDC desktopDC = GetDC(desktopWnd); + RECT rc; + GetWindowRect(desktopWnd, &rc); + + m_width = rc.right - rc.left; + m_height = rc.bottom - rc.top; + 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); + + 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]; + + m_hwnd = CreateWindowExW(WS_EX_TOPMOST, L"ReactOS_Fading_BG", NULL, WS_POPUP, + rc.left, rc.top, m_width, m_height, + m_owner, NULL, shell32_hInstance, (LPVOID)this); + ShowWindow(m_hwnd, SW_SHOW); + + } + + ~FadeHandler() + { + if (m_hwnd) + DestroyWindow(m_hwnd); + UnregisterClassW(L"ReactOS_Fading_BG", shell32_hInstance); + 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; + } + + 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 ? m_hwnd : m_owner; + } +}; + + +LRESULT WINAPI FadeHandler::Proc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch(uMsg) + { + case WM_NCCREATE: + { + LPCREATESTRUCT lpcs = reinterpret_cast(lParam); + FadeHandler* info = static_cast(lpcs->lpCreateParams); + SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG)info); + SetTimer(hWnd, 0x12345, 200, NULL); + break; + } + case WM_PAINT: + { + FadeHandler* info = reinterpret_cast(GetWindowLongPtr(hWnd, GWLP_USERDATA)); + if (info) + { + PAINTSTRUCT paint; + HDC hdc = BeginPaint(hWnd, &paint); + info->Blt(hdc); + EndPaint(hWnd, &paint); + } + return 0; + } + case WM_TIMER: + if (wParam == 0x12345) + { + FadeHandler* info = reinterpret_cast(GetWindowLongPtr(hWnd, GWLP_USERDATA)); + if (info && info->Step()) + InvalidateRect(hWnd, NULL, TRUE); + else + KillTimer(hWnd, 0x12345); + return 0; + } + break; + default: + break; + } + return DefWindowProc(hWnd, uMsg, wParam, lParam); +} + + + /************************************************************************* * ConfirmDialog [internal] * @@ -737,8 +916,9 @@ { TRACE("(%p)\n", hWndOwner); + FadeHandler fade(hWndOwner); /* FIXME: use lpwstrReason */ - if (ConfirmDialog(hWndOwner, IDS_RESTART_PROMPT, IDS_RESTART_TITLE)) + if (ConfirmDialog(fade.Wnd(), IDS_RESTART_PROMPT, IDS_RESTART_TITLE)) { HANDLE hToken; TOKEN_PRIVILEGES npr; @@ -799,7 +979,8 @@ EXTERN_C int WINAPI LogoffWindowsDialog(HWND hWndOwner) { - DialogBox(shell32_hInstance, MAKEINTRESOURCE(IDD_LOG_OFF), hWndOwner, LogOffDialogProc); + FadeHandler fade(hWndOwner); + DialogBox(shell32_hInstance, MAKEINTRESOURCE(IDD_LOG_OFF), fade.Wnd(), LogOffDialogProc); return 0; } @@ -870,12 +1051,14 @@ TRACE("(%p)\n", hWndOwner); + FadeHandler fade(hWndOwner); + /* If the DLL cannot be found for any reason, then it simply uses a dialog box to ask if the user wants to shut down the computer. */ if(!msginaDll) { TRACE("Unable to load msgina.dll.\n"); - ExitWindowsDialog_backup(hWndOwner); + ExitWindowsDialog_backup(fade.Wnd()); return; } @@ -884,7 +1067,7 @@ if(pShellShutdownDialog) { /* Actually call the function */ - DWORD returnValue = pShellShutdownDialog(hWndOwner, NULL, FALSE); + DWORD returnValue = pShellShutdownDialog(fade.Wnd(), NULL, FALSE); switch(returnValue) { @@ -937,6 +1120,6 @@ /* If the function cannot be found, then revert to using the backup solution */ TRACE("Unable to find the 'ShellShutdownDialog' function"); FreeLibrary(msginaDll); - ExitWindowsDialog_backup(hWndOwner); + ExitWindowsDialog_backup(fade.Wnd()); } }