使用GetFrontBufferData(),&将屏幕截图放置在单独的设备后备缓冲区中 [英] using GetFrontBufferData(), & place screenshot in separate device backbuffer

查看:160
本文介绍了使用GetFrontBufferData(),&将屏幕截图放置在单独的设备后备缓冲区中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好吧,所以对于经常使用它的人-这应该是一个超级简单的问题.

Ok, so for anyone who's used it much - this should be a SUPER easy question.

我只是在网上搜索一种使用DirectX/Direct3D拍摄更快的屏幕截图的方法,每个人都在谈论GetFrontBufferData()以及它的美妙之处.

I was just searching online for a way to use DirectX/Direct3D to take faster screenshots, and everyone was talking about GetFrontBufferData() and how wonderful it was.

我已经尝试了一段时间,但开始认为他们使用了截屏"一词不正确...我的电话成功了,但是我却没有得到截屏".

I've pounded at it for a while but am starting to think they're using the term "screenshot" incorrectly... My call succeeds, but I never get a "screenshot".

因此,问题是,您是否可以实际使用GetFrontBufferData()制作整个桌面的真实屏幕截图,还是仅仅是在限制范围内从前缓冲区读取像素的一种方法?d3d设备的绘图区域?

So the question is, can you actually use GetFrontBufferData() to make a REAL screenshot of the whole desktop, or is it merely a way to read the pixels out of the front buffer WITHIN the confines of your d3d-device's drawing area?

(成功后,我希望看到窗口内的绘图区域能像老式电视,电视中的电视,电视中的电视,电视中的电视那样发挥效果.除了黑色,我什么都没得到)

(Upon success, I'd have expected to see the drawing area within my window do that old tv-in a tv-in a tv-in a tv-in a tv - kind of effect. I got nothing but black.)

因此,我能够使用屏幕截图,但似乎无法将图像放入应用程序窗口的缓冲区中.

So, I was able to get a screenshot to work, but can't seem to put my image into the buffer for my app window.

起初,我认为这是因为它们是分开的设备,但是我尝试在正确的设备上创建第二个表面,然后手动复制内容.(尽管我可能会复制错误((现在不重要)),但对于正确的设备,对Stretchrect的调用仍然失败.

At first, I thought this was because they were separate devices, but I've tried creating a second surface on the correct device and then manually copying the contents over. (Although I might be copying it wrong ((not important right now)) the call to the stretchrect still fails for the correct device.

有什么主意为什么不能让我将这个表面应用到我的后缓冲上?

Any idea why it won't let me apply this surface to my backbuffer???

D3DDISPLAYMODE          d3dDisplayMode;
D3DPRESENT_PARAMETERS   d3dPresentationParameters;

if( (d3d=Direct3DCreate9(D3D_SDK_VERSION))==NULL )
    exit(1);
D3DCAPS9 d3dcps;
d3d->GetDeviceCaps(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,&d3dcps);
DWORD targets = d3dcps.NumSimultaneousRTs;
// TODO: ^ make a way for user to select one from this and put it into i
DWORD i=D3DADAPTER_DEFAULT;

if( d3d->GetAdapterDisplayMode(i,&d3dDisplayMode)==D3DERR_INVALIDCALL )
    exit(1);

ZeroMemory(&d3dPresentationParameters,sizeof(D3DPRESENT_PARAMETERS));//Fills a block of memory with zeros.
d3dPresentationParameters.Windowed = TRUE;
d3dPresentationParameters.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
d3dPresentationParameters.BackBufferFormat = d3dDisplayMode.Format;//d3dDisplayMode.Format;//D3DFMT_A8R8G8B8;
d3dPresentationParameters.BackBufferCount = 1;
d3dPresentationParameters.BackBufferHeight = d3dDisplayMode.Height;
d3dPresentationParameters.BackBufferWidth = d3dDisplayMode.Width;
d3dPresentationParameters.MultiSampleType = D3DMULTISAMPLE_NONE;
d3dPresentationParameters.MultiSampleQuality = 0;
d3dPresentationParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dPresentationParameters.hDeviceWindow = hwDesktop;
d3dPresentationParameters.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
d3dPresentationParameters.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;

if( d3d->CreateDevice(i,D3DDEVTYPE_HAL,hwDesktop,D3DCREATE_SOFTWARE_VERTEXPROCESSING,&d3dPresentationParameters,&d3dcdev) != D3D_OK )
    exit(1);

if( d3dcdev->CreateOffscreenPlainSurface(d3dDisplayMode.Width,d3dDisplayMode.Height,D3DFMT_A8R8G8B8,D3DPOOL_SYSTEMMEM,&sfScrn, NULL) != D3D_OK )
    exit(1);

if( d3dcdev->GetFrontBufferData(0,sfScrn) != D3D_OK)
    exit(1);   

// we now have a screenshot in sfScrn. 
// let's render it to a separate device in our app window!
d3dPresentationParameters.hDeviceWindow = hwDrawArea;
if( d3d->CreateDevice(i,D3DDEVTYPE_HAL,hwDrawArea,D3DCREATE_SOFTWARE_VERTEXPROCESSING,&d3dPresentationParameters,&d3drdev) != D3D_OK )
    exit(1);
d3drdev->GetBackBuffer(0,0,D3DBACKBUFFER_TYPE_MONO,&sfBackBuffer);
if( d3drdev->CreateOffscreenPlainSurface(d3dDisplayMode.Width,d3dDisplayMode.Height,D3DFMT_A8R8G8B8,D3DPOOL_SYSTEMMEM,&sfTransfer, NULL) != D3D_OK )
    exit(1);

D3DLOCKED_RECT lockedRectScrn, lockedRectTransfer;
ZeroMemory(&lockedRectScrn, sizeof(D3DLOCKED_RECT));
ZeroMemory(&lockedRectTransfer, sizeof(D3DLOCKED_RECT));
if(sfScrn->LockRect(&lockedRectScrn,NULL,D3DLOCK_READONLY) != D3D_OK 
    || sfTransfer->LockRect(&lockedRectTransfer,NULL,0) != D3D_OK )
    exit(1);
memcpy((BYTE*)lockedRectTransfer.pBits,(BYTE*)lockedRectScrn.pBits,lockedRectScrn.Pitch*d3dDisplayMode.Height);
sfScrn->UnlockRect();
sfTransfer->UnlockRect();

while(true)
{
    if(d3drdev != NULL)
    {
        d3drdev->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_XRGB(75,0,0),1.0f,0);
        if(D3D_OK!=d3drdev->StretchRect(sfTransfer,NULL,sfBackBuffer,NULL,D3DTEXF_NONE))
        {
            MessageBox(NULL,"failed to use stretchrect","",0);
            exit(1);
        }
        if(d3drdev->BeginScene())
        {
            d3drdev->EndScene();
        }
        d3drdev->Present(NULL,NULL,NULL,NULL);
    }
}

Edit2:

哦!因此,显然您不能在D3DPOOL_SYSTEMMEM中的曲面上使用StretchRect(),但必须在D3DPOOL_SYSTEMMEM中使用GetFronBufferData().

Oh! So apparently you can't use StretchRect() on surfaces that are in D3DPOOL_SYSTEMMEM, but you must use GetFronBufferData() on D3DPOOL_SYSTEMMEM.

推荐答案

是.您可以使用 GetFrontBufferData 捕获Windows桌面.作为证明,我可以提供这个最近的问题海报工作的地方,除非桌面使用16位彩色.它可能会给您一些有关如何正确使用它的见解.

Yes. you can capture the Windows desktop using GetFrontBufferData. As proof I can offer this recent question where the poster had it working, except not when the desktop was using 16-bit colour. It might give you some insight in how to use it correctly.

但是,不是,这不是 GetFrontBufferData 的真正目的".真正的目的是允许Direct3D游戏捕获游戏本身的屏幕截图,而不管游戏是窗口式还是全屏形式,最重要的是,游戏是否使用多重采样.

But no, that's the not the "true purpose" of GetFrontBufferData. It's real purpose is to allow Direct3D games to capture screenshots of the game itself regardless of whether the game is windowed or fullscreen, and most importantly, whether or not the game is using multisampling or not.

GetFrontBufferData 并不是用来捕获Windows桌面屏幕截图的更好方法.它可能碰巧比其他方法快,但这不是为什么它存在的原因.

GetFrontBufferData isn't designed to be a better method to take screenshots of the Windows desktop. It might happen to be faster than other methods, but that's not why it exists.

这篇关于使用GetFrontBufferData(),&将屏幕截图放置在单独的设备后备缓冲区中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆