lengshizai 2024-04-12 09:51 采纳率: 31.7%
浏览 18
已结题

C++后台截屏遇到的问题

截屏过程中发现 有的程序后台截屏可以 有的程序截屏就是纯黑色的图形,请找下原因指导
同样的代码 。


#include <windows.h>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <fstream>
#include <string>

bool SaveMatAsBMP(const cv::Mat& img, const std::string& fileName)
{
    try {
        cv::imwrite(fileName, img);
        return true;
    }
    catch (const cv::Exception& e) {
        std::cerr << "Error saving image: " << e.what() << std::endl;
        return false;
    }
}

cv::Mat CaptureWindow(HWND hWnd, HDC hWindowDC, HDC hMemoryDC, HBITMAP hBitmap, int width, int height)
{
    SelectObject(hMemoryDC, hBitmap);

    BitBlt(hMemoryDC, 0, 0, width, height, hWindowDC, 0, 0, SRCCOPY);

    cv::Mat img(height, width, CV_8UC3);
    BITMAPINFO bmi = { 0 };
    bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmi.bmiHeader.biWidth = width;
    bmi.bmiHeader.biHeight = -height; // 注意高度是负数,表示从底部开始绘制
    bmi.bmiHeader.biPlanes = 1;
    bmi.bmiHeader.biBitCount = 24;
    bmi.bmiHeader.biCompression = BI_RGB;

    GetDIBits(hMemoryDC, hBitmap, 0, height, img.data, &bmi, DIB_RGB_COLORS);

    return img;
}

int main() {
    HWND hWndTarget = FindWindow(L"UnrealWindow", NULL); // 替换为你想要截图的窗口标题

    if (hWndTarget == NULL) {
        std::cerr << "Unable to find the target window." << std::endl;
        return -1;
    }

    // 创建设备上下文和位图资源
    HDC hWindowDC = GetDC(hWndTarget);
    HDC hMemoryDC = CreateCompatibleDC(hWindowDC);

    RECT windowRect;
    GetWindowRect(hWndTarget, &windowRect);
    int width = windowRect.right - windowRect.left;
    int height = windowRect.bottom - windowRect.top;

    HBITMAP hBitmap = CreateCompatibleBitmap(hWindowDC, width, height);
    HGDIOBJ oldBitmap = SelectObject(hMemoryDC, hBitmap);
    Sleep(3000);
    int numIterations = 10; // 替换成您期望的循环次数
    for (int i = 0; i < numIterations; ++i)
    {
        cv::Mat screenshot = CaptureWindow(hWndTarget, hWindowDC, hMemoryDC, hBitmap, width, height);
        std::string outputFileName = "screenshot_" + std::to_string(i) + ".bmp";

        if (!SaveMatAsBMP(screenshot, outputFileName)) {
            std::cerr << "Failed to save screenshot " << i << std::endl;
            // 可能需要提前结束程序或执行其他恢复逻辑
        }
        Sleep(1000);
    }

    // 清理资源
    SelectObject(hMemoryDC, oldBitmap);
    DeleteObject(hBitmap);
    DeleteDC(hMemoryDC);
    ReleaseDC(hWndTarget, hWindowDC);

    return 0;

}

黑屏图形如下:

img

正常截屏如下:

img

  • 写回答

12条回答 默认 最新

  • 普通 网友 2024-04-12 09:52
    关注

    以下参考免费微信小程序:皆我百晓生 作答,并由妄北y整理回复。

    遇到截屏程序返回纯黑色图像的问题,可能是由于多种原因造成的。下面是一些可能的原因和相应的解决方案:

    1. 窗口可见性问题:有时候,窗口可能没有被渲染到可以被截屏的状态。这可能是因为窗口正在被移动或者大小调整。确保窗口是可见的,并且已经渲染完成。

    2. 硬件加速问题:某些程序可能使用硬件加速,这可能导致截屏失败。可以尝试禁用硬件加速来看是否能够解决问题。这通常在程序的设置中可以找到。

    3. 权限问题:确保你的程序有足够的权限去截取目标窗口的屏幕。如果是在多用户环境下,可能需要管理员权限。

    4. 子窗口问题:如果你正在尝试截取的窗口是一个子窗口(例如,一个弹出菜单或者对话框),那么可能需要调整代码来定位正确的设备上下文(DC)。

    5. 显卡驱动问题:有时候显卡驱动的问题也会导致截屏失败。确保你的显卡驱动是最新的。

    6. 使用PrintScreen而不是截屏API:尝试使用PrintScreen功能,而不是直接从窗口的设备上下文中获取图像。

    7. 使用第三方库:如果上述方法都不奏效,可以考虑使用第三方截屏库,如DirectXTK或者SharpDX,这些库可能提供了更稳定的截屏解决方案。

    下面是一些修改建议,你可以尝试在你的代码中应用:

    • 确保窗口不是最小化的:
    ShowWindow(hWndTarget, SW_NORMAL);
    UpdateWindow(hWndTarget);
    
    • 尝试在截屏前刷新窗口,使其内容被渲染:
    InvalidateRect(hWndTarget, NULL, TRUE);
    UpdateWindow(hWndTarget);
    
    • 如果目标窗口是一个子窗口,获取其父窗口的设备上下文可能更为合适:
    HWND hWndParent = GetParent(hWndTarget);
    if (hWndParent) {
        HDC hParentDC = GetDC(hWndParent);
        // ... 使用hParentDC代替hWindowDC ...
        ReleaseDC(hWndParent, hParentDC);
    }
    

    请注意,这些只是一些可能的解决方案,具体问题还需要具体分析。如果问题依然存在,可能需要进一步调试和检查目标程序的状态。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(11条)

报告相同问题?

问题事件

  • 系统已结题 4月20日
  • 已采纳回答 4月12日
  • 创建了问题 4月12日

悬赏问题

  • ¥15 软件工程用例图的建立(相关搜索:软件工程用例图|画图)
  • ¥15 如何在arcgis中导出拓扑关系表
  • ¥15 处理数据集文本挖掘代码
  • ¥15 matlab2017
  • ¥15 在vxWorks下TCP/IP编程,总是connect()报错,连接服务器失败: errno = 0x41
  • ¥15 AnolisOs7.9如何安装 Qt_5.14.2的运行库
  • ¥20 求:怎么实现qt与pcie通信
  • ¥50 前后端数据顺序不一致问题,如何解决?(相关搜索:数据结构)
  • ¥15 基于蒙特卡罗法的中介效应点估计代码
  • ¥15 罗技G293和UE5.3