繁体   English   中英

如何获取 MS Windows 窗口的“显示流”?

[英]How to get the "display stream" of a MS Windows window?

我有一个程序(我们称之为“虚拟屏幕”),它创建一个全屏窗口并启动任意程序,并在钩子( CBTProc )的帮助下获取启动程序创建的窗口的句柄。 我从这些句柄中检索窗口的内容(使用GetDIBits )并将其显示在“虚拟屏幕”窗口中。
目前,这个“虚拟屏幕”复制窗口的内容,然后重新绘制它们,使其工作,有点像镜像软件。
这是我获取窗口内容的方法:

struct WindowContent {
    void *pixel;
    int width;
    int height;
};
WindowContent getWindowContent(HWND hWnd, int height, int width)
{
    WindowContent content;
    WINDOWINFO windowInfo;
    GetWindowInfo(hWnd, &windowInfo);
    content.height = windowInfo.rcClient.right - windowInfo.rcClient.left;
    content.width = windowInfo.rcClient.bottom - windowInfo.rcClient.top;
    HDC hdc = GetDC(hWnd);
    HDC captureHdc = CreateCompatibleDC(hdc);
    HBITMAP hBitmap = CreateCompatibleBitmap(hdc, content.width, content.height);
    HGDIOBJ oldHdc = SelectObject(captureHdc, hBitmap);
    BitBlt(captureHdc, 0, 0, content.width, content.height, hdc, 0, 0, SRCCOPY|CAPTUREBLT);
    SelectObject(captureHdc, oldHdc);
    DeleteDC(captureHdc);
    BITMAPINFO outputBitmapInfo = {};
    outputBitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    GetDIBits(hdc, hBitmap, 0, 0, NULL, &outputBitmapInfo, DIB_RGB_COLORS);
    content.pixel = (BYTE *)malloc(outputBitmapInfo.bmiHeader.biSizeImage);
    outputBitmapInfo.bmiHeader.biCompression = BI_RGB;  
    outputBitmapInfo.bmiHeader.biBitCount = 32;
    GetDIBits(hdc, hBitmap, 0, outputBitmapInfo.bmiHeader.biHeight, content.pixel, &outputBitmapInfo, DIB_RGB_COLORS);
    return content;
}

我的问题是,如何删除复制部分,如何在“虚拟屏幕”上创建一个区域作为这些程序的窗口输出?
强调我试图使创建的窗口成为“虚拟屏幕”上的区域,我不希望在桌面上隐藏或显示额外的窗口。 在我的研究中,我查看了 Windows DWM DLL 并发现了一些未记录的函数( SignalRedirectionStartCompleteMilConnection_CreateChannel ),它们的名称看起来与我想做的事情相关联,但我认为我不应该使用它们,因为它们没有记录。 此外,代码使用的是 Win32 API,但我不介意使用其他 Windows API 或其他语言(C#、DX* ...)。

忘了提,我已经考虑过使用 DWM 缩略图的东西,但是对于我想要做的事情来说它不够可靠。 据我了解,Windows 10 在幕后使用 DX 进行所有显示输出、GDI,甚至 Vulkan / OpenGL 程序,有人用它制作了一个从窗口 () 获取 DX 10 纹理的库。 是否可以制作类似的东西,对于特定的HWND ,将其“输出”设置为纹理或内存中的某个区域(交换链重定向?)而不是屏幕,然后在另一个程序中显示输出(在我的情况下,在“虚拟屏幕”窗口中)?

DWM 是一个值得一看的地方。 它有一些记录在案的功能,可以让您至少更接近您想要的东西。

您可以使用DwmRegisterThumbnail将您的窗口注册为“缩略图”查看器。 然后您(可能)调用DwmUpdateThumbnailProperties来告诉它如何绘制到您的窗口(例如,设置不透明度、绘制到的矩形,以及是绘制整个源窗口还是仅绘制其客户区)。 完成后,您可以调用DwmUnregisterThumbnail取消显示它。

这只是更接近您想要的东西——它使您不必将位图从源复制到您自己的窗口中——但这就是它所做的全部。 目标应用程序仍将在其他地方运行自己的窗口。

如果您想进一步隐藏应用程序,您可以创建另一个桌面,并在该桌面上显示该应用程序。 如果您不提供切换桌面的方法,则可以很好地隐藏它。 另一方面,有一些外部工具可以让用户改变桌面,让他们直接看到应用程序。

另一个需要考虑的途径(对于应用程序的子集)是 COM。 COM 支持的部分内容是拥有一个 COM 服务器,该服务器在某个 COM 客户端窗口的框架内显示其输出。 这不再是曾经的大事,但是(我相信)支持它的所有代码仍然可用。 但是,它只适用于专门为支持它而编写的应用程序(老实说,这不是一个很大的数字)。 用于此的代码也不是微不足道的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM