c++代码高效屏幕录制,高手帮忙携程delphi的,谢谢!
- C/C++ code
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; // 用来保存位图信息的结构
// DirectX初始化。返回当前表面获取一张屏幕位图的存储空间大小
int DX_Init()
{
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;
}
// 捕捉屏幕。rect: 区域。scrBuff: 输出缓冲。scrBuffSize: 缓冲区大小
BOOL CaptureScreen(RECT &rect, BYTE *scrBuff, UINT 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;
}
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;
}
[解决办法]
Mark
[解决办法]
- Delphi(Pascal) code
unit Unit4;interfaceuses windows,DirectX;type RECT = TRect;varlpDD: IDirectDraw = Nil;lpDDSPrime: IDIRECTDRAWSURFACE = Nil;lpDDSBack: IDIRECTDRAWSURFACE = Nil;lpDDSGdi: IDIRECTDRAWSURFACE = Nil;lpSurf: IDIRECTDRAWSURFACE = Nil;DDSdesc: TDDSURFACEDESC ;m_b24: LongBOOL = TRUE;//rfbServerInitMsg m_scrinfo;m_bmrect: RECT;type_BMInfo = record bmi: BITMAPINFO; truecolour: LongBOOL; cmap: array [0..256-1] of RGBQUAD;end;var m_bminfo : _BMInfo; // 用来保存位图信息的结构 function DX_Init: DWORD;function CaptureScreen(var rect: RECT; scrBuff: PBYTE; scrBuffSize: UINT): LongBool;function SaveBitmapToFile(bitmap:PBITMAP;lpFileName: PChar;lpBuf: PChar): BOOL;function GetBitmapFromScreen(lpFileName: PChar): BOOL;implementationfunction memcpy(dest:Pointer;src:Pointer;count:Integer): Integer;begin Result := count; Move(src^,dest^,Result);end;// DirectX初始化。返回当前表面获取一张屏幕位图的存储空间大小function DX_Init: DWORD;var hr: HRESULT;begin Result := 0; // 初始化directX hr := DirectDrawCreate(Nil, lpDD, Nil); if (FAILED(hr)) then Exit; hr := lpDD.SetCooperativeLevel(0, DDSCL_NORMAL); if (FAILED(hr)) then Exit; ZeroMemory(@DDSdesc, sizeof(DDSdesc)); DDSdesc.dwSize := sizeof(DDSdesc); DDSdesc.dwFlags := DDSD_CAPS; DDSdesc.ddsCaps.dwCaps := DDSCAPS_PRIMARYSURFACE; hr := lpDD.CreateSurface(DDSdesc, lpDDSPrime, Nil); if (FAILED(hr)) then Exit; hr := lpDD.GetGDISurface(lpDDSGdi); if (FAILED(hr)) then Exit; ZeroMemory(@DDSdesc, sizeof(DDSdesc)); DDSdesc.dwSize := sizeof(DDSdesc); DDSdesc.dwFlags := DDSD_ALL; hr := lpDDSPrime.GetSurfaceDesc(DDSdesc); if (FAILED(hr)) then Exit; // 初始化位图信息 if ((DDSdesc.dwFlags and DDSD_WIDTH) = DDSD_WIDTH) and ((DDSdesc.dwFlags and DDSD_HEIGHT) = DDSD_HEIGHT) then begin m_bmrect.left := 0; m_bmrect.top := 0; m_bmrect.right := DDSdesc.dwWidth; m_bmrect.bottom := DDSdesc.dwHeight; end else Exit; 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) then m_bminfo.truecolour := TRUE else m_bminfo.truecolour := FALSE; ZeroMemory(@DDSdesc, sizeof(DDSdesc)); DDSdesc.dwSize := sizeof(DDSdesc); DDSdesc.dwFlags := DDSD_CAPS or DDSD_HEIGHT or 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, Nil); if (FAILED(hr)) then Exit; //hr = lpDDSPrime->QueryInterface( IID_IDirectDrawSurface3, (LPVOID *)&lpSurf); //if (FAILED(hr)) // return FALSE; case (m_bminfo.bmi.bmiHeader.biBitCount) of 32,24:begin // 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) div 8); m_bminfo.bmi.bmiHeader.biXPelsPerMeter := (1024*1000) div 1024; m_bminfo.bmi.bmiHeader.biYPelsPerMeter := (768*1000) div 768; m_bminfo.bmi.bmiHeader.biClrUsed := 0; m_bminfo.bmi.bmiHeader.biClrImportant := 0; end; end; Result := m_bminfo.bmi.bmiHeader.biSizeImage;end;// 捕捉屏幕。rect: 区域。scrBuff: 输出缓冲。scrBuffSize: 缓冲区大小function CaptureScreen(var rect: RECT; scrBuff: PBYTE; scrBuffSize: UINT): LongBool;var hr: HRESULT; surfdesc: TDDSURFACEDESC; srcbuffpos, destbuffpos: PBYTE;begin hr := 0; Result := False; hr := lpDDSBack.BltFast(rect.left,rect.top,lpDDSPrime,@rect,DDBLTFAST_NOCOLORKEY or DDBLTFAST_WAIT); if (FAILED(hr)) then Exit; ZeroMemory(@surfdesc, sizeof(surfdesc)); surfdesc.dwSize := sizeof(surfdesc); hr := lpDDSBack.Lock(@rect, surfdesc, DDLOCK_READONLY or DDLOCK_WAIT or DDLOCK_SURFACEMEMORYPTR (*|DDLOCK_NOSYSLOCK*), 0); //hr = lpDDSPrime->Lock(&rect, &surfdesc, DDLOCK_READONLY | DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR /*|DDLOCK_NOSYSLOCK*/, NULL); if (FAILED(hr)) then Exit; // copy the data into our buffer// m_scrinfo.format.bitsPerPixel = 24; srcbuffpos := PByte( surfdesc.lpSurface); destbuffpos := scrBuff; memcpy( destbuffpos, srcbuffpos,m_bminfo.bmi.bmiHeader.biSizeImage); // unlock the primary surface //lpDDSPrime->Unlock(surfdesc.lpSurface); lpDDSBack.Unlock(surfdesc.lpSurface); Result := TRUE;end;function SaveBitmapToFile(bitmap:PBITMAP;lpFileName: PChar;lpBuf: PChar): BOOL;var dwWritten: DWORD; bmfHdr: BITMAPFILEHEADER; bi: BITMAPINFOHEADER; fh: THANDLE;begin Result := False; fh := INVALID_HANDLE_VALUE; 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, Nil, CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL or FILE_FLAG_SEQUENTIAL_SCAN, 0); if (fh = INVALID_HANDLE_VALUE) then Exit; bmfHdr.bfType := $4D42; // "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, PChar(@bmfHdr)^, sizeof(BITMAPFILEHEADER), dwWritten, Nil); WriteFile(fh, Pchar(@bi)^,sizeof(BITMAPINFOHEADER), dwWritten, Nil); WriteFile(fh, Pchar(lpBuf)^,bitmap^.bmWidth*bitmap^.bmHeight*bitmap^.bmBitsPixel, dwWritten, NiL); FlushFileBuffers(fh); CloseHandle(fh); Result := true;end;function GetBitmapFromScreen(lpFileName: PChar): BOOL;var lpBuf: Pchar; hBitmap,hOld: windows.HBITMAP ; hDC,hcDC: windows.HDC; bb: BITMAP; b: BITMAPINFO; hp,fh: THANDLE ; dwX,dwY: DWORD;begin fh := INVALID_HANDLE_VALUE; //*************** dwX := GetSystemMetrics(SM_CXSCREEN); dwY := GetSystemMetrics(SM_CYSCREEN); hDC := GetDC(0); hcDC:=CreateCompatibleDC(hDC); hBitmap:=CreateCompatibleBitmap(hDC,dwX,dwY); hOld :=windows.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:=PChar(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(0,hDC); DeleteDC(hcDC); DeleteObject(hBitmap); DeleteObject(hOld); HeapFree(hp,0,lpBuf); Result := true;end;end.
[解决办法]
如果释放有问题请在
- Delphi(Pascal) code
...end.
[解决办法]
测试了一下,速度还不错,如果不存盘,仅只是存到内存,包括HeapAlloc/HeapFree在内,一共使用了410719毫秒。平均4.1~4.1毫秒一幅.
[解决办法]
僵哥 好人!mark一下