|
|
#include "priv.h"
#include "fadetsk.h"
#include "apithk.h"
/// Fade Rect Support
// {2DECD184-21B0-11d2-8385-00C04FD918D0}
const GUID TASKID_Fader = { 0x2decd184, 0x21b0, 0x11d2, { 0x83, 0x85, 0x0, 0xc0, 0x4f, 0xd9, 0x18, 0xd0 } };
CFadeTask::CFadeTask() : CRunnableTask(RTF_DEFAULT) { ASSERT(g_bRunOnNT5); // This should only get created on NT5
WNDCLASSEX wc = {0};
if (!GetClassInfoEx(g_hinst, TEXT("SysFader"), &wc)) { wc.cbSize = sizeof(wc); wc.lpfnWndProc = DefWindowProc; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hInstance = g_hinst; wc.lpszClassName = TEXT("SysFader"); wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1); // NULL;
if (!RegisterClassEx(&wc)) return; }
_hwndFader = CreateWindowEx(WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOPMOST | WS_EX_TOOLWINDOW, TEXT("SysFader"), TEXT("SysFader"), WS_POPUP, 0, 0, 0, 0, NULL, (HMENU) 0, g_hinst, NULL); }
CFadeTask::~CFadeTask() { if (_hwndFader) DestroyWindow(_hwndFader); }
#define ALPHASTART (200)
BOOL CFadeTask::FadeRect(PRECT prc, PFNFADESCREENRECT pfn, LPVOID pvParam) { if (IsRunning() == IRTIR_TASK_RUNNING) return FALSE;
InterlockedExchange(&_lState, IRTIR_TASK_NOT_RUNNING);
_rect = *prc; _pfn = pfn; _pvParam = pvParam;
POINT pt; POINT ptSrc = {0, 0}; SIZE size;
// prc and pt are in screen coordinates.
pt.x = _rect.left; pt.y = _rect.top;
// Get the size of the rectangle for the blits.
size.cx = RECTWIDTH(_rect); size.cy = RECTHEIGHT(_rect);
// Get the DC for the screen and window.
HDC hdcScreen = GetDC(NULL); if (hdcScreen) { HDC hdcWin = GetDC(_hwndFader); if (hdcWin) { // If we don't have a HDC for the fade, then create one.
if (!_hdcFade) { _hdcFade = CreateCompatibleDC(hdcScreen); if (!_hdcFade) goto Stop;
// Create a bitmap that covers the fade region, instead of the whole screen.
_hbm = CreateCompatibleBitmap(hdcScreen, size.cx, size.cy); if (!_hbm) goto Stop;
// select it in, saving the old bitmap's handle
_hbmOld = (HBITMAP)SelectBitmap(_hdcFade, _hbm); }
// Get the stuff from the screen and squirt it into the fade dc.
BitBlt(_hdcFade, 0, 0, size.cx, size.cy, hdcScreen, pt.x, pt.y, SRCCOPY);
// Now let user do it's magic. We're going to mimic user and start with a slightly
// faded, instead of opaque, rendering (Looks smoother and cleaner.
BlendLayeredWindow(_hwndFader, hdcWin, &pt, &size, _hdcFade, &ptSrc, ALPHASTART);
// Now that we have it all build up, display it on screen.
SetWindowPos(_hwndFader, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); Stop: ReleaseDC(_hwndFader, hdcWin); }
ReleaseDC(NULL, hdcScreen); }
if (_pfn) _pfn(FADE_BEGIN, _pvParam);
return TRUE; }
#define FADE_TIMER_ID 10
#define FADE_TIMER_TIMEOUT 10 // milliseconds
#define FADE_TIMEOUT 350 // milliseconds
#define FADE_ITERATIONS 35
#define QUAD_PART(a) ((a)##.QuadPart)
void CFadeTask::_StopFade() { if (_hwndFader) { SetWindowPos(_hwndFader, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_HIDEWINDOW); }
if (_pfn) _pfn(FADE_END, _pvParam);
if (_hdcFade) { if (_hbmOld) { SelectBitmap(_hdcFade, _hbmOld); } DeleteDC(_hdcFade); _hdcFade = NULL; } if (_hbm) { DeleteObject(_hbm); _hbm = NULL; } } STDMETHODIMP CFadeTask::RunInitRT(void) { BOOL fRet = FALSE; LARGE_INTEGER liDiff; LARGE_INTEGER liFreq; LARGE_INTEGER liStart; DWORD dwElapsed; BYTE bBlendConst;
// Start the fade timer and the count-down for the fade.
QueryPerformanceFrequency(&liFreq); QueryPerformanceCounter(&liStart);
// Do this until the conditions specified in the loop.
while ( TRUE ) { // Calculate the elapsed time in milliseconds.
QueryPerformanceCounter(&liDiff); QUAD_PART(liDiff) -= QUAD_PART(liStart); dwElapsed = (DWORD)((QUAD_PART(liDiff) * 1000) / QUAD_PART(liFreq));
if (dwElapsed >= FADE_TIMEOUT) { goto Stop; }
bBlendConst = (BYTE)(ALPHASTART * (FADE_TIMEOUT - dwElapsed) / FADE_TIMEOUT);
if (bBlendConst <= 1) { goto Stop; }
// Since only the alpha is updated, there is no need to pass
// anything but the new alpha function. This saves a source copy.
BlendLayeredWindow(_hwndFader, NULL, NULL, NULL, NULL, NULL, bBlendConst); Sleep(FADE_TIMER_TIMEOUT); }
Stop: _StopFade(); return S_OK; }
|