Look at this function, for example. It takes the window handle, the (client area) coordinates, width and height of the rectangle and returns in EAX a pointer to a buffer containing in each DWORD the color of a pixel in BGR format: the low byte is for blue, the next for green, the third for red. The fourth byte is probably not guaranteed to always contain 0, so it's better to mask it somehow.
If the function fails, it sets the carry flag and returns an error code in EAX.
The buffer is allocated each time the function is called, which is not an optimal solution, of course.
captureRect: FRAME hWnd, x, y, w, h
USES rbx,rdi,rsi
LOCALS bih:BITMAPINFOHEADER, pBmp, err
lea rdi,[bih]
mov ecx,sizeof BITMAPINFOHEADER / 4
xor eax,eax
mov [err],rax
rep stosd
invoke GetDC, [hWnd]
mov rsi,rax
test rax,rax
jnz >
mov D[err],1
jmp >>.error
:
invoke CreateCompatibleDC, rsi
mov rdi,rax
test rax,rax
jnz >
mov D[err],2
jmp >>.error
:
invoke CreateCompatibleBitmap, rsi, [w], [h]
mov rbx,rax
test rax,rax
jnz >
mov D[err],3
jmp >>.error
:
invoke SelectObject, rdi, rbx
test rax,rax
jnz >
mov D[err],4
jmp >>.error
:
invoke BitBlt, rdi, 0, 0, [w], [h], rsi, [x], [y], SRCCOPY
test eax,eax
jnz >
mov D[err],5
jmp >>.error
:
mov eax,[w]
shl eax,2
mul D[h]
invoke GlobalAlloc, GMEM_ZEROINIT, rax
mov [pBmp],rax
mov D[bih.biSize],sizeof BITMAPINFOHEADER
mov edx,[w]
mov ecx,[h]
neg ecx
mov [bih.biWidth],edx
mov [bih.biHeight],ecx
neg ecx
mov W[bih.biPlanes],1
mov W[bih.biBitCount],32
mov D[bih.biCompression],BI_RGB
invoke GetDIBits, rdi, rbx, 0, ecx, [pBmp], addr bih, DIB_RGB_COLORS
test eax,eax
jnz >
mov D[err],6
jmp >>.error
:
invoke DeleteDC, rdi
invoke DeleteObject, rbx
invoke ReleaseDC, [hWnd], rsi
mov rax,[pBmp]
clc
.exit
ret
.error
cmp D[err],6
jb >
invoke GlobalFree, [pBmp]
:
cmp D[err],4
jb >
invoke DeleteObject, rbx
:
cmp D[err],3
jb >
invoke DeleteDC, rdi
:
cmp D[err],2
jb >
invoke ReleaseDC, [hWnd], rsi
:
mov eax,[err]
stc
jmp .exit
ENDF