News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

how to create captureScreen like GadwinPrintScreen?

Started by elmo, November 05, 2010, 07:36:57 AM

Previous topic - Next topic

elmo

I try to modify code from http://win32assembly.online.fr/files/CapScreen.txt
below was my code.
It can capture full screen.

But It always produce .bmp file with same size (3MB).
How to repair this problem?

And where I must update my code below, so I can do the these following job:
1. I can capture the screen from a rectangle area
2. I can make file output with difference name. example: Picture1, Picture2,...,PictureN

Thank you



        ;TO ACTIVE THIS, call CapScreen
CapScreen Proc lpFileName:DWORD
LOCAL hdc:HDC
LOCAL memdc:HDC
LOCAL dwBytes:DWORD
LOCAL bitmapfileheader:BITMAPFILEHEADER
LOCAL bitmapinfoheader:BITMAPINFOHEADER
LOCAL colors[256]:RGBQUAD
LOCAL bmpinfo:BITMAPINFO
LOCAL hBitmap:HBITMAP
LOCAL pBits:DWORD
LOCAL dwWidth:DWORD
LOCAL dwHeight:DWORD
LOCAL dwNumColors:DWORD
LOCAL dwBPP:DWORD
LOCAL ColorSize:DWORD




;CREATE DEVICE CONTEXT
invoke CreateDC, addr szDisplay, NULL, NULL, NULL
mov hdc,eax
.IF eax==NULL
;Couldn''t create device context.
invoke MessageBox, 0, addr szNoDC, NULL, 0
ret
.ENDIF



;SCREEN RESOLUTION(800x600,1024x768,1280x1024,1600x1200,1920x1440)
invoke GetDeviceCaps, hdc, HORZRES
mov dwWidth,eax
invoke GetDeviceCaps, hdc, VERTRES
mov dwHeight,eax
;COLOR QUALITY(16bit/32bit)
invoke GetDeviceCaps, hdc, BITSPIXEL
mov dwBPP,eax
.IF (eax<=8)
invoke GetDeviceCaps, hdc, NUMCOLORS
mov dwNumColors,eax
mov dwNumColors,256 ;this one looks bad
.ELSE
mov dwNumColors,0
.ENDIF



;CREATE COMPATIBLE DEVICE CONTEXT
invoke CreateCompatibleDC, hdc
mov memdc,eax
.IF (eax==NULL)
;Couldn''t create compatible device context
invoke DeleteDC, hdc
invoke MessageBox, 0, addr szNoMemDC, NULL, 0
ret
.ENDIF



;CREATE COMPATIBLE BITMAP
mov bmpinfo.bmiHeader.biSize,sizeof BITMAPINFOHEADER
mov eax,dwWidth
mov bmpinfo.bmiHeader.biWidth,eax
mov eax,dwHeight
mov bmpinfo.bmiHeader.biHeight,eax
mov bmpinfo.bmiHeader.biPlanes,1
mov ax,word ptr [dwBPP]
mov bmpinfo.bmiHeader.biBitCount,ax
mov bmpinfo.bmiHeader.biCompression,BI_RGB
mov bmpinfo.bmiHeader.biSizeImage,0
mov bmpinfo.bmiHeader.biXPelsPerMeter,0
mov bmpinfo.bmiHeader.biYPelsPerMeter,0
mov eax,dwNumColors
mov bmpinfo.bmiHeader.biClrUsed,eax
mov bmpinfo.bmiHeader.biClrImportant,eax
invoke CreateDIBSection,hdc,addr bmpinfo, DIB_PAL_COLORS,addr pBits, NULL, 0
mov hBitmap,eax
.IF (eax==NULL)
;Couldn''t create compatible bitmap.
invoke DeleteDC, hdc
invoke DeleteDC, memdc
invoke MessageBox, 0, addr szNoBMP, NULL, 0
ret
.ENDIF



;SELECT BITMAP
invoke SelectObject, memdc, hBitmap
.IF (eax==NULL) || (eax==GDI_ERROR)
;Couldn''t select bitmap.
invoke DeleteDC, hdc
invoke DeleteDC, memdc
invoke MessageBox, 0, addr szNoObj, NULL, 0
ret
.ENDIF



;COPY BITMAP
invoke BitBlt, memdc, 0,0, dwWidth, dwHeight, hdc, 0,0, SRCCOPY
.IF (!eax)
;Couldn''t copy bitmap.
invoke DeleteDC, hdc
invoke DeleteDC, memdc
invoke MessageBox, 0, addr szNoCopy, NULL, 0
ret
.ENDIF



;WRITE FILE TO DISK
mov eax,dwNumColors
.IF (eax!=0)
invoke GetDIBColorTable, memdc, 0, dwNumColors, addr colors
mov dwNumColors,eax
.ENDIF
mov bitmapfileheader.bfType,4D42h
mov eax,dwNumColors
xor edx,edx
mov ecx,sizeof RGBQUAD
mul ecx
mov ColorSize,eax
mov eax,dwWidth
xor edx,edx
mov ecx,dwHeight
mul ecx
xor edx,edx
mov ecx,dwBPP
mul ecx
shr eax,3
add eax,ColorSize
add eax,sizeof BITMAPFILEHEADER
add eax,sizeof BITMAPINFOHEADER
mov bitmapfileheader.bfSize,eax
mov bitmapfileheader.bfReserved1,0
mov bitmapfileheader.bfReserved2,0
mov eax,ColorSize
add eax,sizeof BITMAPFILEHEADER
add eax,sizeof BITMAPINFOHEADER
mov bitmapfileheader.bfOffBits,eax
mov bitmapinfoheader.biSize,sizeof BITMAPINFOHEADER
mov eax,dwWidth
mov bitmapinfoheader.biWidth,eax
mov eax,dwHeight
mov bitmapinfoheader.biHeight,eax
mov bitmapinfoheader.biPlanes,1
mov ax,word ptr [dwBPP]
mov bitmapinfoheader.biBitCount,ax
mov bitmapinfoheader.biCompression,BI_RGB
mov bitmapinfoheader.biSizeImage,0
mov bitmapinfoheader.biXPelsPerMeter,0
mov bitmapinfoheader.biYPelsPerMeter,0
mov eax,dwNumColors
mov bitmapinfoheader.biClrUsed,eax
mov bitmapinfoheader.biClrImportant,0
invoke CreateFile,
SADD("C:\Picture.BMP"), ; screen.bmp ;pointer to name of the file ;put the directory here where you want to save the file
GENERIC_WRITE, ; access (read-write) mode
NULL, ; share mode
NULL, ; pointer to security attributes
CREATE_ALWAYS, ; how to create
FILE_ATTRIBUTE_NORMAL, ; file attributes
NULL
mov hFile,eax
.IF (eax==INVALID_HANDLE_VALUE)
;Couldn''t write file to disk
invoke DeleteObject, hBitmap
invoke DeleteDC, memdc
invoke DeleteDC, hdc
invoke MessageBox, 0, addr szNoFile, NULL, 0
ret
.ENDIF
invoke WriteFile, hFile, addr bitmapfileheader, sizeof BITMAPFILEHEADER,addr dwBytes, NULL
invoke WriteFile, hFile, addr bitmapinfoheader, sizeof BITMAPINFOHEADER,addr dwBytes, NULL
mov eax,dwNumColors
.IF (eax!=0)
invoke WriteFile, hFile, addr colors, ColorSize, addr dwBytes,NULL
.ENDIF
mov eax,dwWidth
xor edx,edx
mov ecx,dwHeight
mul ecx
xor edx,edx
mov ecx,dwBPP
mul ecx
shr eax,3
mov ColorSize,eax
invoke WriteFile, hFile, pBits, ColorSize, addr dwBytes,NULL
invoke CloseHandle, hFile
invoke MessageBox, 0, addr szDone, NULL, 0

invoke DeleteObject ,hBitmap
invoke DeleteDC, memdc
invoke DeleteDC, hdc
ret
CapScreen endp


Added code tags
be the king of accounting programmer world!

MichaelW

Your code works for me (after I added some missing data declarations). The size of the file depends on your display settings. Assuming a 32-bit color setting (32 bits per pixel), and that W and H are the width and height of your screen in pixels, the size of the file should be W*H*4+14+40, where the 14 and 40 are the sizes of the BITMAPFILEHEADER and BITMAPINFOHEADER structures. So for example, 1024*768*4+14+40 = 3145782.

To capture a rectangular area of the screen you could:

In the code that creates the destination bitmap, instead of specifying the width and height of the screen, specify the width and height of the rectangular area.

In the code that copies the pixel data to the destination bitmap (using BitBlt), specify the width and height of the destination, and the coordinates of the source rectangular area.

Make the necessary changes in the BITMAPFILEHEADER and BITMAPINFOHEADER structures, and in the size passed in the last call to WriteFile.
eschew obfuscation

elmo

Nice work!
Thanks MichaelW.




So, I must change this:

Example:
invoke BitBlt, memdc, 0,0, dwWidth, dwHeight, hdc,1,2, SRCCOPY   ;1=X,2=Y
and change dwWidth and dwHeight in part "WRITE FILE TO DISK" to follow "SCREEN RESOLUTION".



but how to show rectangle area position in the screen?
Example: I just type in 4 TextBox
TextBox1: X=10
TextBox2: Y=10
TextBox3: dwWidth=800
TextBox4: dwHeight=600
Then I click a button to show the area that I want to capture base on it.
It always make same result between jpg and bmp file.
But, if I use GadwinPrintScreen, I think .bmp is better than .jpg

What something that make difference between .jpg and .bmp?

Thank you.

be the king of accounting programmer world!

Vortex