我在网上找到了此代码以打印屏幕(截图),但是我不知道如何修改它以将结果保存到PNG文件中。

我可以将位图保存到剪贴板,但现在需要保存到PNG文件。

  • 是否可以从剪贴板中提取位图并将其另存为PNG文件?
  • 可以这样做吗?
  • 如果是,怎么办?

  • 到目前为止,我的代码是:
    #include <iostream>
    #include <windows.h>
    #include <gdiplus.h>
    #include <stdexcept>
    
     using namespace std;
     using namespace Gdiplus;
     using namespace Gdiplus::DllExports;
     using std::runtime_error;
    
    void screenshot(POINT a, POINT b)
    {
    
        HDC     hScreen = GetDC(NULL);
        HDC     hDc     = CreateCompatibleDC(hScreen);
        HBITMAP hBitmap = CreateCompatibleBitmap(hScreen, abs(b.x-a.x), abs(b.y-a.y));
        HGDIOBJ old_obj = SelectObject(hDc, hBitmap);
        BOOL    bRet    =  BitBlt(hDc, 0, 0, abs(b.x-a.y), abs(b.y-a.y), hScreen, a.x, a.y, SRCCOPY);
    
        OpenClipboard(NULL);
        EmptyClipboard();
        SetClipboardData(CF_BITMAP, hBitmap);
        CloseClipboard();
    
    
        SelectObject(hDc, old_obj);
        DeleteDC(hDc);
        ReleaseDC(NULL, hScreen);
        DeleteObject(hBitmap);
    }
    
    int main()
    {
        POINT a,b;
        a.x=386;
        a.y=749;
    
        b.x=686;
        b.y=1049;
    
        screenshot(a,b);
    }
    

    链接-https://causeyourestuck.io/2016/01/12/screenshot-c-win32-api/
    作者Omar AFLAK

    最佳答案

    首先,包括Gdiplus的库。在Visual Studio中,可以使用#pragam关键字,也可以在项目设置中添加Gdiplus.lib。

    接下来,使用Gdiplus::GdiplusStartup初始化Gdiplus

    如前所述,找到编码器CLSID

    在您的代码中,您有abs(b.x-a.y),大概应该是abs(b.x-a.x)。如果以a为起点,则此逻辑可能不起作用。只要确保POINT b大于POINT a即可。或仔细阅读BitBlt的文档

    #include <Windows.h>
    #include "gdiplus.h"
    
    //Visual Studio shortcut for adding library:
    #pragma comment(lib, "Gdiplus.lib")
    
    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
    
        Gdiplus::GetImageEncodersSize(&num, &size);
        if(size == 0)
            return -1;  // Failure
    
        Gdiplus::ImageCodecInfo* pImageCodecInfo = (Gdiplus::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 screenshot(POINT a, POINT b)
    {
        int w = b.x - a.x;
        int h = b.y - a.y;
    
        if(w <= 0) return;
        if(h <= 0) return;
    
        HDC     hScreen = GetDC(HWND_DESKTOP);
        HDC     hDc = CreateCompatibleDC(hScreen);
        HBITMAP hBitmap = CreateCompatibleBitmap(hScreen, w, h);
        HGDIOBJ old_obj = SelectObject(hDc, hBitmap);
        BitBlt(hDc, 0, 0, w, h, hScreen, a.x, a.y, SRCCOPY);
    
        Gdiplus::Bitmap bitmap(hBitmap, NULL);
        CLSID clsid;
    
        GetEncoderClsid(L"image/png", &clsid);
    
        //GDI+ expects Unicode filenames
        bitmap.Save(L"c:\\test\\test.png", &clsid);
    
        SelectObject(hDc, old_obj);
        DeleteDC(hDc);
        ReleaseDC(HWND_DESKTOP, hScreen);
        DeleteObject(hBitmap);
    }
    
    int main()
    {
        Gdiplus::GdiplusStartupInput gdiplusStartupInput;
        ULONG_PTR gdiplusToken;
        Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
    
        RECT      rc;
        GetClientRect(GetDesktopWindow(), &rc);
        POINT a{ 0, 0 };
        POINT b{ 100, 100 };
    
        screenshot(a, b);
    
        Gdiplus::GdiplusShutdown(gdiplusToken);
    
        return 0;
    }
    

    07-28 04:48