|
|
Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
|
Опции темы | Поиск в этой теме | Опции просмотра |
#1
|
|||
|
|||
Класс для снятия скриншотов (Winapi, DirectDraw, DirectX)
Только что закончил, класс для создания скриншотов. Умеет снимать с помощью Winapi, DirectX,DirectDraw. Написан на Delphi XE3, проверен в Win7 x32\64.
Код:
unit DTM_ImageCatcher; interface uses System.Classes,System.SysUtils,Vcl.Controls,Vcl.Graphics, Vcl.Forms,Winapi.Windows,Winapi.D3DX9,Direct3D9,DirectDraw; type TCatchType = (ctWinapi = 0,ctDirectX = 1,ctDDraw); TImageCatcher = class private FBitmap: Vcl.Graphics.TBITMAP; FCatchType: TCatchType; FTargetHandle: HWND; procedure GetTargetRect(out Rect: TRect); procedure GetDDrawData(); procedure GetDirectXData(); procedure GetWinapiData(); procedure GetTargetDimensions(out w, h: integer); procedure GetTargetPosition(out left, top: integer); public constructor Create; procedure Reset; destructor Destroy;override; procedure GetScreenShot(); procedure ActivateTarget; property Bitmap: Vcl.Graphics.TBITMAP read FBitmap write FBitmap; property CatchType: TCatchType read FCatchType write FCatchType; property TargetHandle: HWND read FTargetHandle write FTargetHandle; end; implementation { TImageCather } procedure TImageCatcher.ActivateTarget; begin SetForegroundWindow(TargetHandle); end; constructor TImageCatcher.Create; begin Reset; FBitmap:=Vcl.Graphics.TBitmap.Create; FBitmap.PixelFormat:=pf24bit; end; destructor TImageCatcher.Destroy; begin FreeAndNil(FBitmap); inherited; end; procedure TImageCatcher.GetDDrawData(); var DDSCaps: TDDSCaps; DesktopDC: HDC; DirectDraw: IDirectDraw; Surface: IDirectDrawSurface; SurfaceDesc: TDDSurfaceDesc; x, y, w, h: integer; begin GetTargetDimensions(w, h); GetTargetPosition(x, y); if DirectDrawCreate(nil, DirectDraw, nil) = DD_OK then if DirectDraw.SetCooperativeLevel(GetDesktopWindow, DDSCL_EXCLUSIVE or DDSCL_FULLSCREEN or DDSCL_ALLOWREBOOT) = DD_OK then begin FillChar(SurfaceDesc, SizeOf(SurfaceDesc), 0); SurfaceDesc.dwSize := Sizeof(SurfaceDesc); SurfaceDesc.dwFlags := DDSD_CAPS; SurfaceDesc.ddsCaps.dwCaps := DDSCAPS_PRIMARYSURFACE; SurfaceDesc.dwBackBufferCount := 0; if DirectDraw.CreateSurface(SurfaceDesc, Surface, nil) = DD_OK then begin if Surface.GetDC(DesktopDC) = DD_OK then try Bitmap.Width := Screen.Width; Bitmap.Height := Screen.Height; BitBlt(Bitmap.Canvas.Handle, 0, 0, W, H, DesktopDC, x, y, SRCCOPY); finally Surface.ReleaseDC(DesktopDC); end; end; end; 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; 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); BitBlt(Bitmap.Canvas.Handle, 0, 0, w, h, BMP.Canvas.Handle, x, y, SRCCOPY); BMP.Free; pSurface.UnlockRect; end; procedure TImageCatcher.GetScreenShot(); begin case CatchType of ctWinapi: GetWinapiData(); ctDirectX: GetDirectXData(); ctDDraw: GetDDrawData(); end; SetForegroundWindow(Application.Handle); end; procedure TImageCatcher.GetTargetDimensions(out w, h: integer); var Rect: TRect; begin GetTargetRect(rect); w := Rect.Right - Rect.Left; h := Rect.Bottom - Rect.Top; end; procedure TImageCatcher.GetTargetPosition(out left, top: integer); var Rect: TRect; begin GetTargetRect(rect); left := Rect.Left; top := Rect.Top; end; procedure TImageCatcher.GetTargetRect(out Rect: TRect); begin GetWindowRect(TargetHandle, Rect); end; procedure TImageCatcher.Reset; begin CatchType := ctWinapi; TargetHandle := 0; end; procedure TImageCatcher.GetWinapiData(); var hWinDC: THandle; w, h: integer; begin GetTargetDimensions(w, h); hWinDC := GetWindowDC(TargetHandle); Bitmap.Width := w; Bitmap.Height := h; hWinDC := GetWindowDC(TargetHandle); BitBlt(Bitmap.Canvas.Handle, 0, 0, Bitmap.Width, Bitmap.Height, hWinDC, 0, 0, SRCCOPY); ReleaseDC(TargetHandle, hWinDC); end; end. Как использовать: Создать экзэмпляр класса, присвоить в свойство TargetHandle - HWND требуемого окна, установить режим снятия скриншота(ctWinapi,ctDDraw,ctDirectX), затем при нажатии кнопки выполнить метод класса ActivateClient; затем вызвать GetScreenShot; и в поле Bitmap будет находится скрин окна. Внимание: Использовать режим ctDDraw Только для снятия скрина с видеоплееров и т.д. С простыми окнами оно не будет работать как надо. Последний раз редактировалось CynicRus, 12.04.2014 в 16:14. |
#2
|
||||
|
||||
Direct3D9, DirectDraw — входят в пакет дельфи?
З.Ы. Код немного отформатировать не помешало бы. — Как тебя понимать? — Понимать меня не обязательно. Обязательно меня любить и кормить вовремя. На Delphi, увы, больше не программирую. Рекомендуемая литература по программированию |
#3
|
|||
|
|||
Цитата:
В версии старше Delphi XE2 - входят. Код чутка форматнул. Последний раз редактировалось CynicRus, 12.04.2014 в 16:14. |