DirectX 截屏问题

bamboo2000 2013-08-24 01:07:19
以下三段代码中,只有第一段能截屏,但仍然截不到分层窗口(像QQ的登录窗口),谁能给出一段DirectX的正常截屏代码,效率不要太低!

// ============ 11111 ================
g_pD3DDevice.CreateOffscreenPlainSurface(Screen.Width, Screen.Height, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, pSurface, nil);
g_pD3DDevice.GetFrontBufferData(0, pSurface);
D3DXSaveSurfaceToFile(PWidechar(filename), D3DXIFF_BMP, pSurface, nil, nil);

// ============= 22222 =============
g_pD3DDevice.CreateOffscreenPlainSurface(Screen.Width, Screen.Height, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, pSurface, nil);
g_pD3DDevice.GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, pBackSurface);
D3DXLoadSurfaceFromSurface(pSurface, nil, nil, pBackSurface, nil, nil, D3DX_FILTER_NONE, 0);
D3DXSaveSurfaceToFile(PWidechar(filename), D3DXIFF_BMP, pSurface, nil, nil);

// ============== 33333 =============
g_pD3DDevice.GetRenderTarget( 0, pSurface );
g_pD3DDevice.CreateOffscreenPlainSurface(Screen.Width, Screen.Height, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, pBackSurface, nil);
g_pD3DDevice.GetRenderTargetData( pSurface,pBackSurface );
D3DXSaveSurfaceToFile(PWidechar(filename), D3DXIFF_BMP, pBackSurface, nil, nil);

...全文
387 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
bamboo2000 2013-09-01
  • 打赏
  • 举报
回复
5楼:我自己在Win7禁用Aero效果后测试都是3~4毫秒。
繁重的秋春 2013-08-28
  • 打赏
  • 举报
回复
表示关注,这个技术我也要用到。。。
bamboo2000 2013-08-27
  • 打赏
  • 举报
回复
这段代码可以截屏,速度相当慢,另外发现不能截取QQ等透明窗口的原因了,是因为我把Aero效果关掉了。
bamboo2000 2013-08-27
  • 打赏
  • 举报
回复
用GDI截屏AMD显卡是不是比Intel显卡快啊 AMD7470:1280*1024 i5 8G 3.1毫秒 (快的有点不正常,但截的图的确是正常的,谁能告诉我为何?) GT630:1600*900 i5 4G 36毫秒 代码如下: procedure TForm1.CapScreenGDI(const FileName: string); var nScreenWidth,nScreenHeight: integer; ScreenDc,hCaptureDC: HDC; bmp: TBitmap; e,b,c: int64; begin QueryPerformanceFrequency(c); QueryPerformanceCounter(b); nScreenWidth := GetSystemMetrics(SM_CXSCREEN); nScreenHeight := GetSystemMetrics(SM_CYSCREEN); ScreenDc := GetDC(GetDesktopWindow); hCaptureDC := CreateCompatibleDC(ScreenDc); bmp := TBitmap.Create; bmp.Handle := CreateCompatibleBitmap(ScreenDc,nScreenWidth, nScreenHeight); SelectObject(hCaptureDC,bmp.Handle); BitBlt(hCaptureDC,0,0,nScreenWidth,nScreenHeight,ScreenDc,0,0,SRCCOPY);// or $40000000 ); ReleaseDC(GetDesktopWindow,ScreenDc); DeleteDC(hCaptureDC); QueryPerformanceCounter(e); bmp.SaveToFile(fileName); bmp.Free; Caption := IntToStr( trunc( (e-b)/c * 1000000 ) ); end;
赵4老师 2013-08-26
  • 打赏
  • 举报
回复
仅供参考
//GDI与DX截屏API操作
LPDIRECTDRAW        lpDD       = NULL;
LPDIRECTDRAWSURFACE lpDDSPrime = NULL;
LPDIRECTDRAWSURFACE lpDDSBack  = NULL;
LPDIRECTDRAWSURFACE lpDDSGdi   = NULL;
LPDIRECTDRAWSURFACE lpSurf     = NULL;

DDSURFACEDESC DDSdesc;
BOOL m_b24=TRUE;
//rfbServerInitMsg m_scrinfo;
RECT    m_bmrect;

struct _BMInfo {
    BITMAPINFO bmi       ;
    BOOL       truecolour;
    RGBQUAD    cmap[256] ;
} m_bminfo; // 用来保存位图信息的结构

int DX_Init() {// DirectX初始化。返回当前表面获取一张屏幕位图的存储空间大小
    HRESULT hr;

    // 初始化directX
    hr = DirectDrawCreate(0, &lpDD, 0);
    if (FAILED(hr)) return FALSE;

    hr = lpDD->SetCooperativeLevel(NULL, DDSCL_NORMAL);
    if (FAILED(hr)) return FALSE;

    ZeroMemory(&DDSdesc, sizeof(DDSdesc));
    DDSdesc.dwSize  = sizeof(DDSdesc);
    DDSdesc.dwFlags = DDSD_CAPS;
    DDSdesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
    hr = lpDD->CreateSurface(&DDSdesc, &lpDDSPrime, 0);
    if (FAILED(hr)) return FALSE;

    hr = lpDD->GetGDISurface(&lpDDSGdi);
    if (FAILED(hr)) return FALSE;

    ZeroMemory(&DDSdesc, sizeof(DDSdesc));
    DDSdesc.dwSize  = sizeof(DDSdesc);
    DDSdesc.dwFlags = DDSD_ALL;
    hr = lpDDSPrime->GetSurfaceDesc(&DDSdesc);
    if (FAILED(hr)) return FALSE;

    // 初始化位图信息
    if ((DDSdesc.dwFlags & DDSD_WIDTH) && (DDSdesc.dwFlags & DDSD_HEIGHT)) {
        m_bmrect.left = m_bmrect.top = 0;
        m_bmrect.right = DDSdesc.dwWidth;
        m_bmrect.bottom = DDSdesc.dwHeight;
    } else return FALSE;

    m_bminfo.bmi.bmiHeader.biCompression = BI_RGB;//BI_BITFIELDS;
    m_bminfo.bmi.bmiHeader.biBitCount = DDSdesc.ddpfPixelFormat.dwRGBBitCount;

    // m_bminfo.truecolour = DDSdesc.ddpfPixelFormat.dwFlags & DDPF_RGB;
    if (m_bminfo.bmi.bmiHeader.biBitCount > 8)
        m_bminfo.truecolour = TRUE;
    else
        m_bminfo.truecolour = FALSE;

    ZeroMemory(&DDSdesc, sizeof(DDSdesc));
    DDSdesc.dwSize = sizeof(DDSdesc);
    DDSdesc.dwFlags = DDSD_CAPS | DDSD_HEIGHT |DDSD_WIDTH;
    DDSdesc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
    DDSdesc.dwHeight = m_bmrect.bottom - m_bmrect.top;
    DDSdesc.dwWidth  = m_bmrect.right  - m_bmrect.left;
    hr = lpDD->CreateSurface(&DDSdesc, &lpDDSBack, 0);
    if (FAILED(hr)) return FALSE;
//  hr = lpDDSPrime->QueryInterface( IID_IDirectDrawSurface3, (LPVOID *)&lpSurf);
//  if (FAILED(hr)) return FALSE;

    switch (m_bminfo.bmi.bmiHeader.biBitCount) {
    case 32:
    case 24:
       // Update the bitmapinfo header
       m_b24 = TRUE;
       m_bminfo.bmi.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
       m_bminfo.bmi.bmiHeader.biWidth = 1024;
       m_bminfo.bmi.bmiHeader.biHeight = 768;
       m_bminfo.bmi.bmiHeader.biPlanes = 1;
//     m_bminfo.bmi.bmiHeader.biBitCount = 24;
       m_bminfo.bmi.bmiHeader.biCompression = BI_RGB;
       m_bminfo.bmi.bmiHeader.biSizeImage = abs((m_bminfo.bmi.bmiHeader.biWidth * m_bminfo.bmi.bmiHeader.biHeight * m_bminfo.bmi.bmiHeader.biBitCount)/8);
       m_bminfo.bmi.bmiHeader.biXPelsPerMeter = (1024*1000)/1024;
       m_bminfo.bmi.bmiHeader.biYPelsPerMeter = (768*1000)/768;
       m_bminfo.bmi.bmiHeader.biClrUsed   = 0;
       m_bminfo.bmi.bmiHeader.biClrImportant = 0;
       break;
    }

    return m_bminfo.bmi.bmiHeader.biSizeImage;
}

BOOL CaptureScreen(RECT &rect, BYTE *scrBuff, UINT scrBuffSize) {// 捕捉屏幕。rect: 区域。scrBuff: 输出缓冲。scrBuffSize: 缓冲区大小
    HRESULT hr=0;

    hr = lpDDSBack->BltFast(rect.left,rect.top,lpDDSPrime,&rect,DDBLTFAST_NOCOLORKEY | DDBLTFAST_WAIT);
    if (FAILED(hr)) return FALSE;

    DDSURFACEDESC surfdesc;
    ZeroMemory(&surfdesc, sizeof(surfdesc));
    surfdesc.dwSize = sizeof(surfdesc);

    hr = lpDDSBack->Lock(&rect, &surfdesc, DDLOCK_READONLY | DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR /*|DDLOCK_NOSYSLOCK*/, NULL);
//  hr = lpDDSPrime->Lock(&rect, &surfdesc, DDLOCK_READONLY | DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR /*|DDLOCK_NOSYSLOCK*/, NULL);
    if (FAILED(hr)) return FALSE;

    // copy the data into our buffer
    BYTE * destbuffpos, * srcbuffpos;
//  m_scrinfo.format.bitsPerPixel = 24;
    srcbuffpos = (BYTE *) surfdesc.lpSurface;
    destbuffpos = scrBuff;

    memcpy( destbuffpos, srcbuffpos,m_bminfo.bmi.bmiHeader.biSizeImage);

    // unlock the primary surface
//  lpDDSPrime->Unlock(surfdesc.lpSurface);
    lpDDSBack->Unlock(surfdesc.lpSurface);
    return TRUE;
}

int SaveBitmapToFile(BITMAP *bitmap, LPSTR lpFileName,char *lpBuf) {
   DWORD dwWritten;
   BITMAPFILEHEADER   bmfHdr;
   BITMAPINFOHEADER   bi;
   HANDLE          fh=NULL;
   bi.biSize = sizeof(BITMAPINFOHEADER);
   bi.biWidth= bitmap->bmWidth;
   bi.biHeight = bitmap->bmHeight;
   bi.biPlanes = 1;
   bi.biBitCount      = bitmap->bmBitsPixel*8;
   bi.biCompression   = BI_RGB;
   bi.biSizeImage     = 0;
   bi.biXPelsPerMeter = 0;
   bi.biYPelsPerMeter = 0;
   bi.biClrUsed       = 0;
   bi.biClrImportant  = 0;
   fh = CreateFile(lpFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
   if (fh == INVALID_HANDLE_VALUE) return FALSE;
   bmfHdr.bfType = 0x4D42; // "BM"
   bmfHdr.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)+bitmap->bmWidth*bitmap->bmHeight*bitmap->bmBitsPixel;
   bmfHdr.bfReserved1 = 0;
   bmfHdr.bfReserved2 = 0;
   bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER);
   WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);
   WriteFile(fh, (char *)&bi,sizeof(BITMAPINFOHEADER), &dwWritten, NULL);
   WriteFile(fh, (char *)lpBuf,bitmap->bmWidth*bitmap->bmHeight*bitmap->bmBitsPixel, &dwWritten, NULL);
   FlushFileBuffers(fh);
   CloseHandle(fh);
   return true;
}

//(1)获取屏幕绘图设备
//(2)创建一个与屏幕绘图设备相兼容的内存绘图设备
//(2)在内存中创建一个与屏幕绘图设备相兼容的图像对象
//(3)将屏幕设备中的图像复制到内存绘图设备中
//(4)将内存图像保存到文件中
//相关函数:
//GetDIBits:按位的方式返回指定的BITMAP,并按指定的格式存储到内存中
int GetBitmapFromScreen(char *lpFileName) {
    char *lpBuf;
    HBITMAP hBitmap,hOld ;
    HDC hDC,hcDC;
    BITMAP bb;
    BITMAPINFO b;
    HANDLE hp,fh=NULL;
    DWORD dwX,dwY;

    dwX=GetSystemMetrics(SM_CXSCREEN);
    dwY=GetSystemMetrics(SM_CYSCREEN);
    hDC=GetDC(NULL);
    hcDC=CreateCompatibleDC(hDC);
    hBitmap=CreateCompatibleBitmap(hDC,dwX,dwY);
    hOld=(HBITMAP)SelectObject(hcDC,hBitmap);
    BitBlt(hcDC,0, 0,dwX,dwY, hDC, 0, 0, SRCCOPY);
    bb.bmWidth=dwX;
    bb.bmHeight =dwY;
    bb.bmPlanes = 1;
    bb.bmWidthBytes=bb.bmWidth*3;
    bb.bmBitsPixel=3;
    bb.bmType=0;
    b.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    b.bmiHeader.biWidth        =dwX;
    b.bmiHeader.biHeight       =dwY;
    b.bmiHeader.biPlanes       =1;
    b.bmiHeader.biBitCount     =3*8;
    b.bmiHeader.biCompression  =BI_RGB;
    b.bmiHeader.biSizeImage    =0;
    b.bmiHeader.biXPelsPerMeter=0;
    b.bmiHeader.biYPelsPerMeter=0;
    b.bmiHeader.biClrUsed      =0;
    b.bmiHeader.biClrImportant =0;
    b.bmiColors[0].rgbBlue     =8;
    b.bmiColors[0].rgbGreen    =8;
    b.bmiColors[0].rgbRed      =8;
    b.bmiColors[0].rgbReserved =0;
    hp=GetProcessHeap();
    lpBuf=(char *)HeapAlloc(hp,HEAP_ZERO_MEMORY,bb.bmHeight*bb.bmWidth*4);
    GetDIBits(hcDC,hBitmap,0,dwY,lpBuf,&b,DIB_RGB_COLORS);
    SaveBitmapToFile(&bb,lpFileName,lpBuf);
    ReleaseDC(NULL,hDC);
    DeleteDC(hcDC);
    DeleteObject(hBitmap);
    DeleteObject(hOld);
    HeapFree(hp,0,lpBuf);
    return true;
}

bamboo2000 2013-08-26
  • 打赏
  • 举报
回复
高手哪儿去了,给可行的代码就行,语言无所谓啊
bamboo2000 2013-08-25
  • 打赏
  • 举报
回复
怎么没人理我啊,因为我把Delphi贴过来的缘故吗? 忘了说明一下我是Win7,Delphi 2010,程序调用的DirectX9

19,468

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧