Olá!
Usando GCC 64 Bits.
Código: Selecionar todos
// Arquivo fonte C para salvar uma captura de tela no formato BMP
#pragma BEGINDUMP
#include <windows.h>
#include <stdio.h>
HB_FUNC(SAVE_SCREENSHOT)
{
const char *filename;
int screenWidth, screenHeight;
HDC hScreenDC, hMemoryDC;
HBITMAP hBitmap;
BITMAP bmp;
BITMAPFILEHEADER bmfHeader;
BITMAPINFOHEADER bi;
DWORD dwBmpSize, dwSizeofDIB, dwBytesWritten;
HANDLE hDIB, hFile;
char *lpbitmap;
// Obtém o nome do arquivo passado como parâmetro
filename = hb_parc(1); // Obtém o parâmetro de string da função Harbour
// Obtém as dimensões da tela
screenWidth = GetSystemMetrics(SM_CXSCREEN);
screenHeight = GetSystemMetrics(SM_CYSCREEN);
// Captura o dispositivo da tela (HDC)
hScreenDC = GetDC(NULL);
hMemoryDC = CreateCompatibleDC(hScreenDC);
// Cria um bitmap compatível com o dispositivo da tela
hBitmap = CreateCompatibleBitmap(hScreenDC, screenWidth, screenHeight);
SelectObject(hMemoryDC, hBitmap);
// Copia a tela para o bitmap
BitBlt(hMemoryDC, 0, 0, screenWidth, screenHeight, hScreenDC, 0, 0, SRCCOPY);
// Estrutura para salvar o bitmap como BMP
GetObject(hBitmap, sizeof(BITMAP), &bmp);
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = bmp.bmWidth;
bi.biHeight = -bmp.bmHeight; // Negativo para linha de cima ser a primeira
bi.biPlanes = 1;
bi.biBitCount = 32;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
dwBmpSize = ((bmp.bmWidth * bi.biBitCount + 31) / 32) * 4 * bmp.bmHeight;
hDIB = GlobalAlloc(GHND, dwBmpSize); // Aloca memória para o DIB
lpbitmap = (char *)GlobalLock(hDIB); // Bloqueia o ponteiro para o DIB
// Copia o bitmap para o buffer
GetDIBits(hMemoryDC, hBitmap, 0, (UINT)bmp.bmHeight, lpbitmap, (BITMAPINFO *)&bi, DIB_RGB_COLORS);
// Cria o arquivo BMP
hFile = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
dwSizeofDIB = dwBmpSize + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
bmfHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
bmfHeader.bfSize = dwSizeofDIB;
bmfHeader.bfType = 0x4D42; // BM
WriteFile(hFile, (LPSTR)&bmfHeader, sizeof(BITMAPFILEHEADER), &dwBytesWritten, NULL);
WriteFile(hFile, (LPSTR)&bi, sizeof(BITMAPINFOHEADER), &dwBytesWritten, NULL);
WriteFile(hFile, (LPSTR)lpbitmap, dwBmpSize, &dwBytesWritten, NULL);
// Libera os recursos
GlobalUnlock(hDIB); // Desbloqueia o DIB
GlobalFree(hDIB); // Libera a memória do DIB
CloseHandle(hFile); // Fecha o arquivo
DeleteObject(hBitmap); // Deleta o objeto bitmap
DeleteDC(hMemoryDC); // Deleta o contexto de memória
ReleaseDC(NULL, hScreenDC); // Libera o contexto da tela
hb_retl(TRUE); // Retorna sucesso
}
#pragma ENDDUMP
Gerando objeto .o(LIB)
Código: Selecionar todos
gcc -c screenshot.c -o screenshot.o -D_CRT_SECURE_NO_WARNINGS -lgdi32 -lkernel32 -luser32
Salvando em PNG BMP é muito grande o arquivo.
Código: Selecionar todos
#pragma BEGINDUMP
#include <windows.h>
#include <stdio.h>
#include <png.h>
HB_FUNC(SAVE_SCREENSHOT)
{
const char *filename;
int screenWidth, screenHeight;
HDC hScreenDC, hMemoryDC;
HBITMAP hBitmap;
BITMAP bmp;
BITMAPFILEHEADER bmfHeader;
BITMAPINFOHEADER bi;
DWORD dwBmpSize, dwSizeofDIB, dwBytesWritten;
HANDLE hDIB, hFile;
char *lpbitmap;
// Obtém o nome do arquivo passado como parâmetro
filename = hb_parc(1); // Obtém o parâmetro de string da função Harbour
// Obtém as dimensões da tela
screenWidth = GetSystemMetrics(SM_CXSCREEN);
screenHeight = GetSystemMetrics(SM_CYSCREEN);
// Captura o dispositivo da tela (HDC)
hScreenDC = GetDC(NULL);
hMemoryDC = CreateCompatibleDC(hScreenDC);
// Cria um bitmap compatível com o dispositivo da tela
hBitmap = CreateCompatibleBitmap(hScreenDC, screenWidth, screenHeight);
SelectObject(hMemoryDC, hBitmap);
// Copia a tela para o bitmap
BitBlt(hMemoryDC, 0, 0, screenWidth, screenHeight, hScreenDC, 0, 0, SRCCOPY);
// Estrutura para salvar o bitmap como BMP
GetObject(hBitmap, sizeof(BITMAP), &bmp);
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = bmp.bmWidth;
bi.biHeight = -bmp.bmHeight; // Negativo para linha de cima ser a primeira
bi.biPlanes = 1;
bi.biBitCount = 32;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
dwBmpSize = ((bmp.bmWidth * bi.biBitCount + 31) / 32) * 4 * bmp.bmHeight;
hDIB = GlobalAlloc(GHND, dwBmpSize); // Aloca memória para o DIB
lpbitmap = (char *)GlobalLock(hDIB); // Bloqueia o ponteiro para o DIB
// Copia o bitmap para o buffer
GetDIBits(hMemoryDC, hBitmap, 0, (UINT)bmp.bmHeight, lpbitmap, (BITMAPINFO *)&bi, DIB_RGB_COLORS);
// Agora vamos salvar a imagem como PNG usando libpng
// Abrir o arquivo PNG
hFile = CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
hb_retl(FALSE); // Falhou ao abrir o arquivo
return;
}
// Usando libpng para salvar a imagem em PNG
png_structp png = png_create_write_struct(PNG_LIBPNG_VER, NULL, NULL, NULL);
png_infop info = png_create_info_struct(png);
if (png == NULL || info == NULL) {
hb_retl(FALSE); // Erro ao criar a estrutura png
return;
}
png_set_filter_type(png, PNG_FILTER_DEFAULT);
png_set_compression_level(png, PNG_COMPRESSION_TYPE);
png_set_output_to_file(png, hFile);
png_write_info(png, info);
png_byte* row = (png_byte*)malloc(4 * screenWidth);
for (int y = 0; y < screenHeight; ++y) {
for (int x = 0; x < screenWidth; ++x) {
row[x] = *(lpbitmap + (y * screenWidth + x));
}
png_write_row(png, row);
}
// Finalizar o arquivo PNG
png_write_end(png, NULL);
fclose(hFile);
free(row);
// Libera os recursos
GlobalUnlock(hDIB);
GlobalFree(hDIB);
CloseHandle(hFile);
DeleteObject(hBitmap);
DeleteDC(hMemoryDC);
ReleaseDC(NULL, hScreenDC);
hb_retl(TRUE); // Retorna sucesso
}
#pragma ENDDUMP
Pra PNG precisa da ZLIB e LIBPNG.
Código: Selecionar todos
gcc -c screenshot.c -o screenshot.o -I"C:/libs/libpng/include" -I"C:/libs/zlib/include" -DPNG_DEBUG -O2 -D_CRT_SECURE_NO_WARNINGS
Não testei ainda... No Linux agora.
Saudações,
Itamar M. Lins Jr.