2016-12-31 2 views
0

Я пытаюсь захватить игровое окно, используя SendMessage с wm_paint и wm_printclient.Захват игрового окна с помощью wm_paint

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

Проблема заключается в том, что я получаю черный прямоугольник в результате SendMessage, для любого графического движка и даже для любой программы/окна.

void capture::captureProgramScreen(HWND hwnd, tImage* res) 
{ 
    RECT rc; 

    GetWindowRect(hwnd, &rc); 

    //create 
    HDC hdcScreen = GetDC(NULL); 
    HDC hdc = CreateCompatibleDC(hdcScreen); 
    HBITMAP hbmp = CreateCompatibleBitmap(hdcScreen, rc.right - rc.left, rc.bottom - rc.top); 
    res->width = rc.right - rc.left - 17; 
    res->height = rc.bottom - rc.top - 39; 

    res->absoluteTop = rc.top; 
    res->absoluteLeft = rc.left; 

    SelectObject(hdc, hbmp); 




    SendMessage(hwnd, WM_PRINTCLIENT, (int)hdc, PRF_CHILDREN | PRF_CLIENT | PRF_ERASEBKGND | PRF_NONCLIENT | PRF_OWNED); 


    BITMAPINFO MyBMInfo = { 0 }; 
    MyBMInfo.bmiHeader.biSize = sizeof(MyBMInfo.bmiHeader); 


    if (0 == GetDIBits(hdc, hbmp, 0, 0, NULL, &MyBMInfo, DIB_RGB_COLORS)) 
    { 
     res->error = true; 
     res->errorcode = 2; 
     return; 
    } 


    res->v = std::vector<BYTE>(MyBMInfo.bmiHeader.biSizeImage); 


    MyBMInfo.bmiHeader.biBitCount = 32; 
    MyBMInfo.bmiHeader.biCompression = BI_RGB; 

    MyBMInfo.bmiHeader.biHeight = abs(MyBMInfo.bmiHeader.biHeight); 

    if (0 == GetDIBits(hdc, hbmp, 0, MyBMInfo.bmiHeader.biHeight, &(res->v[0]), &MyBMInfo, DIB_RGB_COLORS)) 
    { 
     res->error = true; 
     res->errorcode = 3; 
     res->width = 0; 
     res->height = 0; 
     res->v.clear(); 
     return; 
    } 


    //4 Bytes per pixel order (B G R A) from [left to right] [bottom to top] 



    return; 
} 

Спасибо!

+1

Вы отправляете сообщение через процессы? Кроме того, какие игровые движки вызывают белый прямоугольник? Может ли это быть движок, который использует DirectX или OpenGL? Они обходят GDI и отображают непосредственно на экране, поэтому их будет сложно захватить. –

+0

Точно OpenGL и DX. Это то, о чем я думал, подумал я с «SendMessage», у меня не было бы этой проблемы, так как это игра, которая пишет в моем hdc. Да, этот код запускается в разном процессе, чем сама игра. – Lolrapa

ответ

2

Есть по крайней мере несколько возможных вопросов:

  1. Не все программы/окна реализуют WM_PRINTCLIENT. Во многих играх даже не реализовано WM_PAINT, поскольку они непрерывно рисуются с требуемой частотой кадров, а не в ответ на необходимость обновления самих себя. Во многих играх используются новые графические API, которые на самом деле не рисуют контекст устройства.

  2. Я не уверен, почему у вас есть два вызова GetDIBits. Первое происходит до того, как вы инициализируете все поля BITMAPINFO, чтобы один из них не удался. Он до сих пор не полностью заполнен ко времени второго вызова.

+0

Спасибо за ваш ответ! Я не делал этот код, но мне нужно получить необработанный массив пикселей из изображения, и я думаю, что он делает два 'GetDIBITS', чтобы получить размер заголовка в первом, а затем ge tonly необработанные пиксели rgba во втором , Я не знаю, правильно ли это сделать, но он работает – Lolrapa

Смежные вопросы