#include <windows.h>
#include <gdiplus.h>
#include <iostream>
#include <filesystem>
#include <chrono>
#include <iomanip>
#include <sstream>
#pragma comment(lib, "Gdiplus.lib")
using namespace Gdiplus;
ULONG_PTR gdiplusToken;
std::wstring StringToWstring(const std::string& s) {
    int len;
    int slength = (int)s.length() + 1;
    len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0);
    wchar_t* buf = new wchar_t[len];
    MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);
    std::wstring r(buf);
    delete[] buf;
    return r;
}
int GetEncoderClsid(const WCHAR* format, CLSID* pClsid) {
    UINT  num = 0;          // number of image encoders
    UINT  size = 0;         // size of the image encoder array in bytes
    ImageCodecInfo* pImageCodecInfo = NULL;
    GetImageEncodersSize(&num, &size);
    if (size == 0)
        return -1;  // Failure
    pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
    if (pImageCodecInfo == NULL)
        return -1;  // Failure
    GetImageEncoders(num, size, pImageCodecInfo);
    for (UINT j = 0; j < num; ++j) {
        if (wcscmp(pImageCodecInfo[j].MimeType, format) == 0) {
            *pClsid = pImageCodecInfo[j].Clsid;
            free(pImageCodecInfo);
            return j;  // Success
        }
    }
    free(pImageCodecInfo);
    return -1;  // Failure
}
void SaveScreenshot(std::string filename, ULONG uQuality = 100) {
    
    ULONG_PTR gdiplusToken;
    GdiplusStartupInput gdiplusStartupInput;
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
    HDC scrdc, memdc;
    HBITMAP membit;
    scrdc = ::GetDC(0);
    int Height = GetSystemMetrics(SM_CYSCREEN);
    int Width = GetSystemMetrics(SM_CXSCREEN);
    memdc = CreateCompatibleDC(scrdc);
    membit = CreateCompatibleBitmap(scrdc, Width, Height);
    HBITMAP hOldBitmap = (HBITMAP)SelectObject(memdc, membit);
    BitBlt(memdc, 0, 0, Width, Height, scrdc, 0, 0, SRCCOPY);
    Gdiplus::Bitmap bitmap(membit, NULL);
    CLSID clsid;
    int ret = GetEncoderClsid(L"image/png", &clsid);
    if (ret != -1)
    {
        std::wstring wfilename = StringToWstring(filename);
        bitmap.Save(wfilename.c_str(), &clsid);
    }
    SelectObject(memdc, hOldBitmap);
    DeleteObject(memdc);
    DeleteObject(membit);
    ::ReleaseDC(0, scrdc);
    GdiplusShutdown(gdiplusToken);
}
std::string GetCurrentTimeStr() {
    auto now = std::chrono::system_clock::now();
    auto in_time_t = std::chrono::system_clock::to_time_t(now);
    std::tm timeinfo;
    localtime_s(&timeinfo, &in_time_t);
    std::stringstream ss;
    ss << std::put_time(&timeinfo, "%Y-%m-%d-%H-%M-%S");
    return ss.str();
}
int main() {
    GdiplusStartupInput gdiplusStartupInput;
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
    std::string filename = "tmp/" + GetCurrentTimeStr() + ".png";
    std::filesystem::create_directories("tmp");
    SaveScreenshot(filename);
    GdiplusShutdown(gdiplusToken);
    return 0;
}