windows-nt/Source/XPSP1/NT/shell/browseui/legacy/fadetsk.cpp
2020-09-26 16:20:57 +08:00

193 lines
5.1 KiB
C++

#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;
}