Как получить «поток отображения» окна MS Windows? - PullRequest
0 голосов
/ 31 марта 2020

У меня есть программа (мы назовем ее «виртуальный экран»), которая создает полноэкранное окно и запускает произвольные программы, а с помощью хуков ( CBTPro c) получает дескрипторы для windows который начал создавать программы. Из этих дескрипторов я извлекаю содержимое windows (используя GetDIBits ) и отображаю его в окне «виртуального экрана».
В настоящее время этот «виртуальный экран» копирует содержимое windows и затем перерисовать их, чтобы они работали, вроде программного обеспечения для зеркалирования.
Вот как я получаю содержимое окна:

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 областью на «виртуальном экране», я не понимаю Не хочу, чтобы дополнительное окно было скрыто или находилось на рабочем столе. В своем исследовании я изучил Windows библиотеки DWM и обнаружил недокументированную функцию (SignalRedirectionStartComplete или MilConnection_CreateChannel), имена которой выглядят связанными с тем, что я хочу сделать, но я не думаю, что мне следует их использовать, как они без документов. Кроме того, в коде используется Win32 API, но я не против использовать другой Windows API или другой язык (C#, DX * ...).

Забыл упомянуть, я уже думал о используя миниатюры DWM, но это не настолько надежно для того, что я пытаюсь сделать. Насколько я понимаю, Windows 10 использует DX под капотом для всего вывода изображения, для GDI и даже для программ Vulkan / OpenGL, и кто-то использовал его для создания библиотеки, которая получает текстуру DX 10 из окна (). Можно ли сделать что-то похожее, чтобы для заданного значения c HWND установить его «выход» для текстуры или некоторой области памяти (перенаправление swapchain?) Вместо экрана, а затем отобразить вывод в другой программе (в моем случае в окне "виртуальный экран")?

1 Ответ

0 голосов
/ 31 марта 2020

DWM был разумным местом для поиска. Он имеет некоторые документированные функции, чтобы вы хотя бы немного приблизились к тому, что вы хотите.

Вы можете зарегистрировать свое окно как средство просмотра "миниатюр", используя DwmRegisterThumbnail. Затем вы (вероятно) вызываете DwmUpdateThumbnailProperties, чтобы сообщить ему, как рисовать в вашем окне (например, установить непрозрачность, прямоугольник для рисования и рисовать ли все исходное окно или только его клиентскую область). Когда вы закончите, вы вызываете DwmUnregisterThumbnail, чтобы отсоединить его от отображения.

Это только немного ближе к тому, что вы хотите - это устраняет необходимость копировать растровые изображения из источника в собственное окно - но это все, что он делает. Целевое приложение по-прежнему будет иметь свое собственное окно, работающее в другом месте.

Если вы хотите сделать больше, чтобы скрыть приложение, вы можете создать другой рабочий стол и отобразить приложение на этом рабочем столе. Если вы не предоставите способ переключения между рабочими столами, это может скрыть его. С другой стороны, существуют внешние инструменты, которые позволяют пользователю менять рабочие столы, что позволяет им видеть приложение напрямую.

Еще одним подходом (для подмножества приложений) будет COM. Часть того, что поддерживает COM, - это наличие COM-сервера, который отображает свои выходные данные в рамке окна некоторого COM-клиента. Это уже не самое важное, что было когда-то, но (я считаю) весь код для его поддержки все еще доступен. Но он работает только для приложений, специально написанных для его поддержки (что, честно говоря, не так уж много). Код для этого тоже не совсем тривиален.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...