簡體   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