8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

该功能仅截取左上角的屏幕截图

zephryl 2月前

38 0

这是我的程序截取的屏幕截图:我尝试制作一个 C++ 程序来截取屏幕截图并将其保存为 png。一切正常,只是它只截取了屏幕左上角的屏幕截图。

这是我的程序截取的屏幕截图:

description

我尝试编写一个 C++ 程序,用于截取屏幕截图并将其保存为 png。除了只截取屏幕左上角的屏幕截图外,其他一切都正常。

问题是我的应用程序拍摄了我的桌面左上角的照片。

我如何截取整个屏幕的屏幕截图?我需要对代码进行哪些更改才能实现我的目标?

这是我的代码:

#define _CRT_SECURE_NO_WARNINGS

#include <windows.h>
#include <objidl.h>
#include <stdio.h>
#include <gdiplus.h>
using namespace Gdiplus;
#pragma comment (lib,"Gdiplus.lib")

int GetEncoderClsid(const WCHAR* format, CLSID* pClsid) {
    UINT num = 0;
    UINT size = 0;
    Gdiplus::ImageCodecInfo* pImageCodecInfo = NULL;

    Gdiplus::GetImageEncodersSize(&num, &size);
    if (size == 0) {
        return -1;
    }

    pImageCodecInfo = (Gdiplus::ImageCodecInfo*)(malloc(size));
    if (pImageCodecInfo == NULL) {
        return -1;
    }

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

    free(pImageCodecInfo);
    return -1;
}

void TakeScreenshot(const wchar_t* file_name) {
    // Get the dimensions of the whole desktop
    int width = GetSystemMetrics(SM_CXVIRTUALSCREEN);
    int height = GetSystemMetrics(SM_CYVIRTUALSCREEN);

    // Create a bitmap to hold the screenshot
    HDC screen_dc = GetDC(NULL);
    HDC mem_dc = CreateCompatibleDC(screen_dc);
    HBITMAP bitmap = CreateCompatibleBitmap(screen_dc, width, height);
    HGDIOBJ old_bitmap = SelectObject(mem_dc, bitmap);

    // Copy the screen contents to the bitmap
    BitBlt(mem_dc, 0, 0, width, height, screen_dc, 0, 0, SRCCOPY);

    // Save the bitmap to a file
    Gdiplus::Bitmap image(bitmap, NULL);
    CLSID png_clsid;
    GetEncoderClsid(L"image/png", &png_clsid);
    image.Save((WCHAR*)file_name, &png_clsid, NULL);

    // Clean up
    SelectObject(mem_dc, old_bitmap);
    DeleteObject(bitmap);
    DeleteDC(mem_dc);
    ReleaseDC(NULL, screen_dc);
}

int main()
{
    Gdiplus::GdiplusStartupInput gdiplusStartupInput;
    ULONG_PTR gdiplusToken;
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

    TakeScreenshot(L"test.png");

    GdiplusShutdown(gdiplusToken);
}

更新的代码:我尝试使用, GetDpiForSystem() 因为我的应用程序应该支持 DPI。但结果仍然相同。

#define _CRT_SECURE_NO_WARNINGS

#include <windows.h>
#include <objidl.h>
#include <stdio.h>
#include <gdiplus.h>
using namespace Gdiplus;
#pragma comment (lib,"Gdiplus.lib")

int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
{
    UINT num = 0;
    UINT size = 0;
    Gdiplus::ImageCodecInfo* pImageCodecInfo = NULL;

    Gdiplus::GetImageEncodersSize(&num, &size);
    if (size == 0) {
        printf("Error: GetImageEncodersSize returned size 0\n");
        return -1;
    }

    pImageCodecInfo = (Gdiplus::ImageCodecInfo*)(malloc(size));
    if (pImageCodecInfo == NULL) {
        printf("Error: malloc failed to allocate memory for ImageCodecInfo\n");
        return -1;
    }

    if (GetImageEncoders(num, size, pImageCodecInfo) != Ok) {
        printf("Error: GetImageEncoders failed\n");
        free(pImageCodecInfo);
        return -1;
    }

    for (UINT j = 0; j < num; ++j) {
        if (wcscmp(pImageCodecInfo[j].MimeType, format) == 0) {
            *pClsid = pImageCodecInfo[j].Clsid;
            free(pImageCodecInfo);
            return j;
        }
    }

    free(pImageCodecInfo);
    return -1;
}

void TakeScreenshot(const wchar_t* file_name)
{
    // Get the dimensions of the whole desktop
    int dpi_x = GetDpiForSystem();
    int dpi_y = GetDpiForSystem();
    int width = GetSystemMetricsForDpi(SM_CXSCREEN, dpi_x);
    int height = GetSystemMetricsForDpi(SM_CYSCREEN, dpi_y);

    if (width == 0 || height == 0) {
        printf("Error: GetSystemMetrics returned invalid screen dimensions\n");
        return;
    }

    printf("Width: %d\n", width);
    printf("Height: %d\n", height);

    // Create a bitmap to hold the screenshot
    HDC screen_dc = GetDC(NULL);
    if (screen_dc == NULL) {
        printf("Error: GetDC failed to get a handle to the screen device context\n");
        return;
    }

    HDC mem_dc = CreateCompatibleDC(screen_dc);
    if (mem_dc == NULL) {
        printf("Error: CreateCompatibleDC failed to create a compatible device context\n");
        ReleaseDC(NULL, screen_dc);
        return;
    }

    // Create a bitmap that is scaled to the appropriate DPI
    HBITMAP bitmap = CreateBitmap(width, height, 1, GetDeviceCaps(screen_dc, BITSPIXEL), NULL);
    if (bitmap == NULL) {
        printf("Error: CreateCompatibleBitmap failed to create a compatible bitmap\n");
        DeleteDC(mem_dc);
        ReleaseDC(NULL, screen_dc);
        return;
    }

    HGDIOBJ old_bitmap = SelectObject(mem_dc, bitmap);

    // Set the DPI of the memory DC to match the system DPI
    SetGraphicsMode(mem_dc, GM_ADVANCED);
    XFORM xform;
    xform.eM11 = (FLOAT)dpi_x / 96;
    xform.eM12 = xform.eM21 = xform.eM22 = 0;
    xform.eDx = xform.eDy = 0;
    SetWorldTransform(mem_dc, &xform);

    // Copy the screen contents to the bitmap
    if (BitBlt(mem_dc, 0, 0, width, height, screen_dc, 0, 0, SRCCOPY) == 0) {
        printf("Error:BitBlt failed to copy screen contents to bitmap\n");
        return;
    }

    // Save the bitmap to a file
    Gdiplus::Bitmap image(bitmap, NULL);
    if (image.GetLastStatus() != Ok) {
        printf("Error: Bitmap constructor failed to create a Bitmap object\n");
        return;
    }

    CLSID png_clsid;
    int r = GetEncoderClsid(L"image/png", &png_clsid);
    if (r == -1)
    {
        printf("Error: unable to find image encoder for MIME type 'image/png'\n");
        return;
    }

    if (image.Save(file_name, &png_clsid, NULL) != Ok) {
        printf("Error: Bitmap::Save failed to save image\n");
        return;
    }

    // Clean up
    SelectObject(mem_dc, old_bitmap);
    DeleteObject(bitmap);
    DeleteDC(mem_dc);
    ReleaseDC(NULL, screen_dc);
}

int main()
{
    GdiplusStartupInput gdiplusStartupInput;
    ULONG_PTR gdiplusToken;
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

    TakeScreenshot(L"test.png");

    GdiplusShutdown(gdiplusToken);
    return 0;
}
帖子版权声明 1、本帖标题:该功能仅截取左上角的屏幕截图
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由zephryl在本站《c》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 输出位图中的像素是否被拉伸?或者它们是否与您在屏幕上看到的像素 1 比 1 相等?

  • @AndreasWenzel 谢谢。现在可以正常工作了。我将发布我的代码作为答案。

  • 代码必须具备 DPI 感知能力,因为显示器的 DPI 可能因系统而异。例​​如,一个用户可能拥有 DPI 为 192 的高分辨率显示器,而另一个用户可能拥有 DPI 为 96 的低分辨率显示器。

    我在调用之前添加了此代码 TakeScreenshot() DPI_AWARENESS_CONTEXT dpi_awareness_context = SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_SYSTEM_AWARE); .

    TakeScreenshot() 我添加之后: SetThreadDpiAwarenessContext(dpi_awareness_context); .

    正如@AndreasWenzel 在评论中所说,这确保我的应用程序具有 DPI 感知能力。

    这段代码运行完美:

    #define _CRT_SECURE_NO_WARNINGS
    
    #include <windows.h>
    #include <objidl.h>
    #include <stdio.h>
    #include <gdiplus.h>
    using namespace Gdiplus;
    #pragma comment (lib,"Gdiplus.lib")
    
    int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
    {
        UINT num = 0;
        UINT size = 0;
        Gdiplus::ImageCodecInfo* pImageCodecInfo = NULL;
    
        Gdiplus::GetImageEncodersSize(&num, &size);
        if (size == 0) {
            printf("Error: GetImageEncodersSize returned size 0\n");
            return -1;
        }
    
        pImageCodecInfo = (Gdiplus::ImageCodecInfo*)(malloc(size));
        if (pImageCodecInfo == NULL) {
            printf("Error: malloc failed to allocate memory for ImageCodecInfo\n");
            return -1;
        }
    
        if (GetImageEncoders(num, size, pImageCodecInfo) != Ok) {
            printf("Error: GetImageEncoders failed\n");
            free(pImageCodecInfo);
            return -1;
        }
    
        for (UINT j = 0; j < num; ++j) {
            if (wcscmp(pImageCodecInfo[j].MimeType, format) == 0) {
                *pClsid = pImageCodecInfo[j].Clsid;
                free(pImageCodecInfo);
                return j;
            }
        }
    
        free(pImageCodecInfo);
        return -1;
    }
    
    void TakeScreenshot(const wchar_t* file_name)
    {
        // Get the dimensions of the whole desktop
        int dpi_x = GetDpiForSystem();
        int dpi_y = GetDpiForSystem();
        int width = GetSystemMetricsForDpi(SM_CXSCREEN, dpi_x);
        int height = GetSystemMetricsForDpi(SM_CYSCREEN, dpi_y);
    
        if (width == 0 || height == 0) {
            printf("Error: GetSystemMetrics returned invalid screen dimensions\n");
            return;
        }
    
        printf("Width: %d\n", width);
        printf("Height: %d\n", height);
    
        // Create a bitmap to hold the screenshot
        HDC screen_dc = GetDC(NULL);
        if (screen_dc == NULL) {
            printf("Error: GetDC failed to get a handle to the screen device context\n");
            return;
        }
    
        HDC mem_dc = CreateCompatibleDC(screen_dc);
        if (mem_dc == NULL) {
            printf("Error: CreateCompatibleDC failed to create a compatible device context\n");
            ReleaseDC(NULL, screen_dc);
            return;
        }
    
        // Create a bitmap that is scaled to the appropriate DPI
        HBITMAP bitmap = CreateBitmap(width, height, 1, GetDeviceCaps(screen_dc, BITSPIXEL), NULL);
        if (bitmap == NULL) {
            printf("Error: CreateCompatibleBitmap failed to create a compatible bitmap\n");
            DeleteDC(mem_dc);
            ReleaseDC(NULL, screen_dc);
            return;
        }
    
        HGDIOBJ old_bitmap = SelectObject(mem_dc, bitmap);
    
        // Set the DPI of the memory DC to match the system DPI
        SetGraphicsMode(mem_dc, GM_ADVANCED);
        XFORM xform;
        xform.eM11 = (FLOAT)dpi_x / 96;
        xform.eM12 = xform.eM21 = xform.eM22 = 0;
        xform.eDx = xform.eDy = 0;
        SetWorldTransform(mem_dc, &xform);
    
        // Copy the screen contents to the bitmap
        if (BitBlt(mem_dc, 0, 0, width, height, screen_dc, 0, 0, SRCCOPY) == 0) {
            printf("Error:BitBlt failed to copy screen contents to bitmap\n");
            return;
        }
    
        // Save the bitmap to a file
        Gdiplus::Bitmap image(bitmap, NULL);
        if (image.GetLastStatus() != Ok) {
            printf("Error: Bitmap constructor failed to create a Bitmap object\n");
            return;
        }
    
        CLSID png_clsid;
        int r = GetEncoderClsid(L"image/png", &png_clsid);
        if (r == -1)
        {
            printf("Error: unable to find image encoder for MIME type 'image/png'\n");
            return;
        }
    
        if (image.Save(file_name, &png_clsid, NULL) != Ok) {
            printf("Error: Bitmap::Save failed to save image\n");
            return;
        }
    
        // Clean up
        SelectObject(mem_dc, old_bitmap);
        DeleteObject(bitmap);
        DeleteDC(mem_dc);
        ReleaseDC(NULL, screen_dc);
    }
    
    int main()
    {
        GdiplusStartupInput gdiplusStartupInput;
        ULONG_PTR gdiplusToken;
        GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
    
        DPI_AWARENESS_CONTEXT dpi_awareness_context = SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_SYSTEM_AWARE);
    
        TakeScreenshot(L"test.png");
    
        SetThreadDpiAwarenessContext(dpi_awareness_context);
    
        GdiplusShutdown(gdiplusToken);
        return 0;
    }
    
返回
作者最近主题: