在 C++ 新创建的窗口中显示屏幕截图

问题描述 投票:0回答:0

我制作了一个截屏并将其保存在本地文件夹中的程序(这很有效)。我删除了那部分并想在新创建的窗口中显示新截取的屏幕截图。一切都很好,截取了屏幕截图,创建了窗口,但唯一的问题是窗口不显示截取的屏幕截图。

如果你想在 Visual Studio 中运行代码,你必须将

Properties -> Linker -> System -> SubSystem (in Visual Studio)
Windows (/SUBSYSTEM:WINDOWS)
更改为
Console (/SUBSYSTEM:CONSOLE)

如何在新创建的窗口中显示新截取的屏幕截图?

这是代码:

#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()
{
    // 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;
    }

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

    HWND hwnd;
    WNDCLASSEX wc;
    HINSTANCE hInstance = GetModuleHandle(NULL);

    // Define window class
    ZeroMemory(&wc, sizeof(WNDCLASSEX));
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = DefWindowProc;
    wc.hInstance = hInstance;
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.lpszClassName = L"ScreenshotWindowClass";
    RegisterClassEx(&wc);

    // Create window
    hwnd = CreateWindowEx(
        WS_EX_CLIENTEDGE,
        L"ScreenshotWindowClass",
        L"Screenshot",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, width, height,
        NULL, NULL, hInstance, NULL);

    if (hwnd == NULL) {
        printf("Error: CreateWindowEx failed to create window\n");
        return;
    }

    // Show screenshot in window
    HDC hdc = GetDC(hwnd);
    Graphics graphics(hdc);
    graphics.DrawImage(&image, 0, 0, width, height);
    ReleaseDC(hwnd, hdc);

    // Display window
    ShowWindow(hwnd, SW_SHOW);
    UpdateWindow(hwnd);

    // Wait for user to close window
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    // Clean up
    UnregisterClass(L"ScreenshotWindowClass", hInstance);


    // 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();

    SetThreadDpiAwarenessContext(dpi_awareness_context);

    GdiplusShutdown(gdiplusToken);
    return 0;
}
c++ windows winapi
© www.soinside.com 2019 - 2024. All rights reserved.