Доброго времени.
Имеется рабочая процедура, которая делает скриншот всего экрана целиком. Необходимо ее переделать, чтобы она брала именно нужную часть. При замене везде Width и Height к примеру на 100х100, в итоге получается черный экран.
Код взят отсюда
ссылка
Что я пропустил?
Рабочий код
procedure TImageCatcher.GetDirectXData();
var
BitsPerPixel: Byte;
pD3D: IDirect3D9;
pSurface: IDirect3DSurface9;
g_pD3DDevice: IDirect3DDevice9;
D3DPP: TD3DPresentParameters;
ARect: TRect;
LockedRect: TD3DLockedRect;
BMP: VCL.Graphics.TBitmap;
i, p: Integer;
x, y: integer;
w, h: integer;
res: BOOL;
begin
GetTargetDimensions(w, h); //Возвращает ширину и высоту экрана
GetTargetPosition(x, y);
BitsPerPixel := 32;
FillChar(d3dpp, SizeOf(d3dpp), 0);
with D3DPP do
begin
Windowed := True;
Flags := D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
SwapEffect := D3DSWAPEFFECT_DISCARD;
BackBufferWidth := Screen.Width;
BackBufferHeight := Screen.Height;
BackBufferFormat := D3DFMT_X8R8G8B8;
end;
pD3D := Direct3DCreate9(D3D_SDK_VERSION);
pD3D.CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, GetDesktopWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, @ D3DPP, g_pD3DDevice);
g_pD3DDevice.CreateOffscreenPlainSurface(Screen.Width, Screen.Height, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, pSurface, nil);
g_pD3DDevice.GetFrontBufferData(0, pSurface);
ARect := Screen.DesktopRect;
pSurface.LockRect(LockedRect, @ ARect, D3DLOCK_NO_DIRTY_UPDATE or D3DLOCK_NOSYSLOCK or D3DLOCK_READONLY);
BMP := VCL.Graphics.TBitmap.Create;
BMP.Width := Screen.Width;
BMP.Height := Screen.Height;
case BitsPerPixel of
8: BMP.PixelFormat := pf8bit;
16: BMP.PixelFormat := pf16bit;
24: BMP.PixelFormat := pf24bit;
32: BMP.PixelFormat := pf32bit;
end;
p := Cardinal(LockedRect.pBits);
for i := 0 to Screen.Height - 1 do
begin
CopyMemory(BMP.ScanLine[i], Ptr(p), Screen.Width * BitsPerPixel div 8);
p := p + LockedRect.Pitch;
end;
Bitmap.SetSize(w, h);
res := BitBlt(Bitmap.Canvas.Handle, 0, 0, w, h, BMP.Canvas.Handle, x, y, SRCCOPY);
BMP.Free;
pSurface.UnlockRect;
end;
Измененный нерабочий код
procedure TImageCatcher.GetDirectXData();
var
BitsPerPixel: Byte;
pD3D: IDirect3D9;
pSurface: IDirect3DSurface9;
g_pD3DDevice: IDirect3DDevice9;
D3DPP: TD3DPresentParameters;
ARect: TRect;
LockedRect: TD3DLockedRect;
BMP: VCL.Graphics.TBitmap;
i, p: Integer;
x, y: integer;
w, h: integer;
res: BOOL;
begin
GetTargetDimensions(w, h);
// w := 50;
// h := 50;
GetTargetPosition(x, y);
BitsPerPixel := 32;
FillChar(d3dpp, SizeOf(d3dpp), 0);
with D3DPP do
begin
Windowed := True;
Flags := D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
SwapEffect := D3DSWAPEFFECT_DISCARD;
BackBufferWidth := 100; //Screen.Width;
BackBufferHeight := 100; //Screen.Height;
BackBufferFormat := D3DFMT_X8R8G8B8;
end;
pD3D := Direct3DCreate9(D3D_SDK_VERSION);
pD3D.CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, GetDesktopWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, @ D3DPP, g_pD3DDevice);
g_pD3DDevice.CreateOffscreenPlainSurface(100 {Screen.Width}, 100 {Screen.Height}, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, pSurface, nil);
g_pD3DDevice.GetFrontBufferData(0, pSurface);
ARect := Rect(0, 0, 100, 100); //Screen.DesktopRect;
pSurface.LockRect(LockedRect, @ ARect, D3DLOCK_NO_DIRTY_UPDATE or D3DLOCK_NOSYSLOCK or D3DLOCK_READONLY);
BMP := VCL.Graphics.TBitmap.Create;
BMP.Width := 100; //Screen.Width;
BMP.Height := 100; //Screen.Height;
case BitsPerPixel of
8: BMP.PixelFormat := pf8bit;
16: BMP.PixelFormat := pf16bit;
24: BMP.PixelFormat := pf24bit;
32: BMP.PixelFormat := pf32bit;
end;
p := Cardinal(LockedRect.pBits);
for i := 0 to 100 {Screen.Height} - 1 do
begin
CopyMemory(BMP.ScanLine[i], Ptr(p), 100 {Screen.Width} * BitsPerPixel div 8);
p := p + LockedRect.Pitch;
end;
Bitmap.SetSize(w, h);
res := BitBlt(Bitmap.Canvas.Handle, 0, 0, w, h, BMP.Canvas.Handle, x, y, SRCCOPY);
BMP.Free;
pSurface.UnlockRect;
end;