winapi - 在另一个进程的窗口句柄(HWND)上绘制位图

标签 winapi gdi bitblt

我有整个屏幕的屏幕截图,它确实是一个有效的BITMAP,因为将其写入文件后,我可以清楚地看到它在那里。

假设我有计算器的窗口句柄。我希望能够不断将 BITMAP (包含桌面屏幕截图)BitBlt 到计算器的窗口上,以便每当计算器打开时,无论它是背景窗口(可见或与其他窗口重叠)还是前景- 它将始终显示最新的屏幕截图,而不是默认的计算器应用程序及其按钮。

我截取了桌面的屏幕截图(位图),并希望使用 StretchDIBits 用我的位图覆盖目标应用程序的区域。但是,当计算器打开时,它没有任何反应/它不会被桌面屏幕截图取代,尽管 StretchDIBits 函数仍然返回复制到目标的扫描线数。

void* calculator_hwnd = (void*) FindWindowA("ApplicationFrameWindow", "Calculator");
void* composition_window = GetWindowDC((HWND)GetDesktopWindow());
if (composition_window)
{
    void* composition_environment = 0;
    if ((composition_environment = CreateCompatibleDC((HDC)composition_window)))
    {
        int window_x_axis = GetSystemMetrics(SM_CXVIRTUALSCREEN);
        int window_y_axis = GetSystemMetrics(SM_CYVIRTUALSCREEN);
        void* bitmap = CreateCompatibleBitmap((HDC)composition_window, window_x_axis, window_y_axis);
        if (bitmap)
        {
            void* composition_bitmap = SelectObject((HDC)composition_environment, bitmap);
            int status = PrintWindow((HWND) GetDesktopWindow(), (HDC)composition_environment, 0x00000002);
            if (!status)
                BitBlt((HDC)composition_environment, 0, 0, window_x_axis, window_y_axis, (HDC)composition_window, 0, 0, SRCCOPY);

            BITMAPINFO* pbi = CreateBitmapInfoStruct((HBITMAP)bitmap);

            BITMAPINFOHEADER* pbih = (PBITMAPINFOHEADER)pbi;
            unsigned char* lpBits = (LPBYTE)GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);

            GetDIBits((HDC)composition_environment, (HBITMAP)bitmap, 0, (WORD)pbih->biHeight, lpBits, pbi,
                            DIB_RGB_COLORS);

            void* calculator_window_environment = GetDC((HWND)calculator_hwnd);
             
            StretchDIBits((HDC)calculator_window_environment, 0, 0, window_x_axis, window_y_axis, 0, 0, window_x_axis, window_y_axis, lpBits, pbi, DIB_RGB_COLORS, SRCCOPY);

            GlobalFree(lpBits);

            SelectObject((HDC)composition_environment, composition_bitmap);
            DeleteObject(bitmap);
        }
    }
    DeleteDC((HDC)composition_environment);
    ReleaseDC((HWND)GetDesktopWindow(), (HDC)composition_window);
}

这是我得到的CreateBitmapInfoStruct

This question说我想做的事情是可能的,但没有解释如何做 - 任何人都可以回答我的代码吗?

最佳答案

操作系统不支持此功能。窗口呈现由窗口所有者(即调用 CreateWindowEx 的线程)决定,并且没有任何外部线程或进程可以 Hook 的自定义点。

虽然您可以渲染成 device context属于外部窗口,您无法(可靠地)找出何时需要更新,也没有任何方法让目标知道它不应该覆盖您刚刚渲染的部分或全部窗口内容.

就 GDI 渲染而言,它实际上仅支持与尚未更新以利用 desktop composition 的应用程序的兼容性。 (在 Windows Vista 中引入)。使用此模型,应用程序可以选择渲染窗口内容,而无需提供重定向表面(如果您希望将 BitBlt/StretchBlt 引入设备上下文,则需要重定向表面)。

因此,本质上,您无法可靠地渲染到不是您创建的窗口上。常见的解决方法是创建一个(部分透明)覆盖窗口,然后您可以移动该窗口以使其与应该增强的窗口保持同步。这无疑会造成非常糟糕的用户体验,因为当用户移动窗口时,您的内容不可避免会落后。

关于winapi - 在另一个进程的窗口句柄(HWND)上绘制位图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75407949/

相关文章:

c++ - Win32 双缓冲绘图黑色背景

c++ - 鼠标在windows中是如何渲染的

c++ - 使用 GDI+ 的带有 PNG 的按钮

c++ - CreateEnhMetaFile 和 PlayEnhMetaFile 导致空白 EMF 文档

winforms - 如何在 Windows 窗体中创建 GDI 泄漏!

c++ - 无法释放设备上下文、HWND,也无法注销 Windows 类 (OpenGL) -

windows - 如何显示 'Send to' 和 'Open With' 上下文菜单?

c++ - 如何将函数指针作为 lpParameter 传递给 CreateThread?

c++ - 获取远程文件的安全细节

c - BitBlt 绘制黑色方 block (Windows 7)