C++ Direct3D Multiple Screen Capture
Asked Answered
M

1

6

Hello Direct3D experts,

I am currently developing an application with Direct3D in order to capture my two monitors desktop (used as extended desktop of course). The following code works well but I am just able to capture the primary display and not the extended desktop (just one screen is captured twice)

How can I adapt this solution for a dual screen capture ?

First of all, I initialize Direct3D:

D3DDISPLAYMODE          d3dDisplayMode;
D3DPRESENT_PARAMETERS   d3dPresentationParameters; //Presentation parameters (backbufferwidth, height...)

if( (pSinfo->g_pD3D=Direct3DCreate9(D3D_SDK_VERSION)) == NULL )
    return FALSE;

if( pSinfo->g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3dDisplayMode) ==  D3DERR_INVALIDCALL )
    return FALSE;

ZeroMemory(&d3dPresentationParameters,sizeof(D3DPRESENT_PARAMETERS));   
d3dPresentationParameters.Windowed = TRUE;
d3dPresentationParameters.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
d3dPresentationParameters.BackBufferFormat = d3dDisplayMode.Format;
d3dPresentationParameters.BackBufferHeight = gScreenRect.bottom = d3dDisplayMode.Height;
d3dPresentationParameters.BackBufferWidth = gScreenRect.right = d3dDisplayMode.Width;
d3dPresentationParameters.MultiSampleType = D3DMULTISAMPLE_NONE;
d3dPresentationParameters.SwapEffect= D3DSWAPEFFECT_DISCARD;
d3dPresentationParameters.hDeviceWindow = hWnd;
d3dPresentationParameters.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
d3dPresentationParameters.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;

pSinfo->uiWidth = d3dDisplayMode.Width;
pSinfo->uiHeight = d3dDisplayMode.Height;

if( pSinfo->g_pD3D->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_REF,hWnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING ,&d3dPresentationParameters,&pSinfo->g_pd3dDevice) != D3D_OK )
    return FALSE;

And then, the loop which perform continuous screenshots and save image data in pData:

while(1)
{
    pSinfo->g_pd3dDevice->GetRenderTarget(0, &pSinfo->pRenderSurface);
    pSinfo->g_pd3dDevice->CreateOffscreenPlainSurface(pSinfo->uiWidth, pSinfo->uiHeight, pSinfo->d3dFormat, D3DPOOL_SYSTEMMEM, &pSinfo->pRenderSurface, NULL);
    pSinfo->g_pd3dDevice->GetFrontBufferData(0, pSinfo->pRenderSurface);

    //D3DXSaveSurfaceToFile("Desktop.bmp", D3DXIFF_BMP, pSinfo->pRenderSurface,NULL, NULL); //Test

    ZeroMemory(&pSinfo->lockedRect, sizeof(D3DLOCKED_RECT));
    pSinfo->pRenderSurface->LockRect(&pSinfo->lockedRect,NULL, D3DLOCK_READONLY);

    memcpy((BYTE*)pSinfo->pData, (BYTE*)pSinfo->lockedRect.pBits, (pSinfo->uiWidth) * pSinfo->uiHeight * pSinfo->uiBitsPerPixels/8);

    pSinfo->pRenderSurface->UnlockRect();
    //InvalidateRect(((CMainFrame*)(pApp->m_pMainWnd))->m_hWnd,NULL,false);
    pSinfo->pRenderSurface->Release();
}

For more clarity about the problem I have and the solution:

I have the two monitors with my extended windows desktop. when capturing the screen I have two screenshots with the main screen and what I want is one screenshot of the main screen and one other with the extended screen.

I guess I have to set up a parameter somewhere indicating that the extended desktop starts at Point.x = 1920 (for 1080p screen) but I just don't know how.

Thank you so much for your help !

Dylan

Screen Scheme

Maganmagana answered 5/9, 2014 at 8:46 Comment(5)
What exactly is this code doing in case you have multiple monitors? What exactly do you want it to do?Frequentation
This code makes a screenshot of my desktop and then I store the screenshots into a file where I can replay them as it was a video. When replaying the screenshots, I have my two screens but it is the same content (The application displays the same screen twice). What I want is to have the entire extended screenMaganmagana
msdn.microsoft.com/en-us/library/windows/desktop/…Jacobah
@Jacobah thank you for the link, I've already checked out this one. Unfortunately I do not understand how this works because if I reset one Device, I have to re-create it later in order to use it again, am I right ?Maganmagana
The line: pSinfo->g_pd3dDevice->GetRenderTarget(0, &pSinfo->pRenderSurface); is not required.Cheng
M
3

All right, I've found the problem right now.

The important thing to notice is the Device Creation with :

pSinfo->g_pD3D->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_REF,hWnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING ,&d3dPresentationParameters,&pSinfo->g_pd3dDevice) != D3D_OK )

Here I was creating a device with D3DADAPTER_DEFAULT which do not take care of other displays. Therefore, I've adapted this code depending of the number of available screens:

for (i = 0; i < NUMBER_OF_DISPLAYS; i++)
{
    pSinfo->g_pD3D->CreateDevice(i,D3DDEVTYPE_REF,hWnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING ,&d3dPresentationParameters,&pSinfo->g_pd3dDevice) != D3D_OK )
}
Maganmagana answered 5/9, 2014 at 11:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.