extern "C" __declspec(dllexport) WINAPI void MakeScreen(char* filename, int Quality)
{
char* temp = new char[150];
GetSystemDirectory(temp,100);
strcat(temp,"\\temp.bmp");
Graphics::TBitmap* bm = new Graphics::TBitmap();
TJPEGImage* JPEG =new TJPEGImage();
HDC dc=GetWindowDC(GetDesktopWindow());
bm->Height = 768;
bm->Width = 1024;
BitBlt(bm->Canvas->Handle,0,0,1024, 768, dc,0,0, SRCCOPY);
bm->SaveToFile(temp);
JPEG->Assign(bm);
JPEG->CompressionQuality = Quality;
JPEG->Compress();
JPEG->SaveToFile(filename);
DeleteFile(temp);
}
// Quality - это качество, чем оно выше, тем увесистее файл
Сохранить DC в *.bmp файл. Как реализировать?
Кто нибудь сталкивался с подобной проблемой, когда скриншот екрана надо сохранить как графический файл? Мне главное сохранить в файл сам битмап, а с заголовком bmp формата я и сам разберусь. Помогите, если знаете.
Если в винде, то надо юзать CreateCompatimbleBitmap, GetDIBits и т. д.
получаешь таким образом набор пикселей и массив RGBQUAD и далее - записываешь все это в файл соответствующим образом (по формату файла)...
Есть примеры в MSDN.
А пример можна?
Цитата: Bard
А пример можна?
Я сам столкнулся однажды с этим, но так как на WinApi это было сложно, решил создать в C++ Buldere dll. С его классом TJPEG - это как 2 байта переслать. Вот код, который сохраняет файл в формате jpeg
Код:
Вот на делфях, сохраняет в файл bmp
Код:
var
b: tbitmap;
dc:hdc;
begin
b:=tbitmap.Create;
b.Width := screen.Width;
b.Height:= screen.Height;
dc:=getdc(0);
bitblt(b.Canvas.Handle,0,0,screen.Width, screen.Height,dc,0,0, SRCCOPY);
b.SaveToFile('c:\test.bmp');
b.Destroy;
releasedc(0,dc);
end;
b: tbitmap;
dc:hdc;
begin
b:=tbitmap.Create;
b.Width := screen.Width;
b.Height:= screen.Height;
dc:=getdc(0);
bitblt(b.Canvas.Handle,0,0,screen.Width, screen.Height,dc,0,0, SRCCOPY);
b.SaveToFile('c:\test.bmp');
b.Destroy;
releasedc(0,dc);
end;
Код на дельфях:
Код:
program Project1;
uses
Windows;
procedure ScreenShot(const Width, Height: LongInt; const Filename: string);
var
Bih: TBitmapInfoHeader;
Bfh: TBitmapFileHeader;
CDC, DC: HDC;
CBmp: HBitMap;
Bmp: Pointer;
BmpInfo: TBitMapInfo;
F, Size, Written: LongWord;
begin
DC := GetDC(0);
CDC := CreateCompatibleDC(DC);
Bih.biSize := SizeOf(TBitmapInfoHeader);
Bih.biWidth := Width;
Bih.biHeight := Height;
Bih.biPlanes := 1;
Bih.biBitCount := GetDeviceCaps(DC, BITSPIXEL) * GetDeviceCaps(DC, PLANES);
if Bih.biBitCount = 32 then Bih.biBitCount := 24;
Size := 3 * Width * Height;
Bfh.bfType := $4D42;
Bfh.bfOffBits := SizeOf(TBitmapFileHeader) + SizeOf(TBitmapInfoHeader);
BmpInfo.bmiHeader := Bih;
CBmp := CreateDIBSection(DC, BmpInfo, 0, Bmp, 0, 0);
SelectObject(CDC, CBmp);
StretchBlt(CDC, 0, 0, Width, Height, DC, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), SRCCOPY);
F := CreateFile(PChar(Filename), GENERIC_WRITE, 0, nil, CREATE_ALWAYS, 0, 0);
WriteFile(F, Bfh, SizeOf(TBitmapFileHeader), Written, nil);
WriteFile(F, Bih, SizeOf(TBitmapInfoHeader), Written, nil);
WriteFile(F, Bmp^, Size, Written, nil);
CloseHandle(F);
end;
begin
ScreenShot(1024,768,'file.bmp');
end.
uses
Windows;
procedure ScreenShot(const Width, Height: LongInt; const Filename: string);
var
Bih: TBitmapInfoHeader;
Bfh: TBitmapFileHeader;
CDC, DC: HDC;
CBmp: HBitMap;
Bmp: Pointer;
BmpInfo: TBitMapInfo;
F, Size, Written: LongWord;
begin
DC := GetDC(0);
CDC := CreateCompatibleDC(DC);
Bih.biSize := SizeOf(TBitmapInfoHeader);
Bih.biWidth := Width;
Bih.biHeight := Height;
Bih.biPlanes := 1;
Bih.biBitCount := GetDeviceCaps(DC, BITSPIXEL) * GetDeviceCaps(DC, PLANES);
if Bih.biBitCount = 32 then Bih.biBitCount := 24;
Size := 3 * Width * Height;
Bfh.bfType := $4D42;
Bfh.bfOffBits := SizeOf(TBitmapFileHeader) + SizeOf(TBitmapInfoHeader);
BmpInfo.bmiHeader := Bih;
CBmp := CreateDIBSection(DC, BmpInfo, 0, Bmp, 0, 0);
SelectObject(CDC, CBmp);
StretchBlt(CDC, 0, 0, Width, Height, DC, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), SRCCOPY);
F := CreateFile(PChar(Filename), GENERIC_WRITE, 0, nil, CREATE_ALWAYS, 0, 0);
WriteFile(F, Bfh, SizeOf(TBitmapFileHeader), Written, nil);
WriteFile(F, Bih, SizeOf(TBitmapInfoHeader), Written, nil);
WriteFile(F, Bmp^, Size, Written, nil);
CloseHandle(F);
end;
begin
ScreenShot(1024,768,'file.bmp');
end.
Переделаный мною код для фасм:
Код:
proc ScreenShot, _Width, _Height, _FileName
invoke CreateDC,"DISPLAY",0,0,0
mov [DC],eax
invoke CreateCompatibleDC,[DC]
mov [CDC],eax
mov [Bih.biSize],44
mov eax,[_Width]
mov [Bih.biWidth],eax
mov eax,[_Height]
mov [Bih.biHeight],eax
mov [Bih.biPlanes],1
mov [Bih.biBitCount],24
mov [Size],3
mov eax,[Size]
imul eax,[_Width]
imul eax,[_Height]
mov [Size],eax
mov [Bfh.bfType],4D42h
mov [Bfh.bfOffBits],64
mov [BmpInfo],Bih
invoke CreateDIBSection,[DC],[BmpInfo],0,Bmp,0,0
mov [CBmp],eax
invoke SelectObject,[CDC],[CBmp]
invoke GetSystemMetrics,SM_CXSCREEN
mov [ResolutionX],eax
invoke GetSystemMetrics,SM_CYSCREEN
mov [ResolutionY],eax
invoke StretchBlt,[CDC],0,0,[_Width],[_Height],[DC],0,0,[ResolutionX],[ResolutionY],SRCCOPY
invoke CreateFile,[_FileName],GENERIC_WRITE,0,0,CREATE_ALWAYS,0,0
mov [F],eax
invoke WriteFile,[F],Bfh,20,Written,0
invoke WriteFile,[F],Bih,44,Written,0
invoke WriteFile,[F],[Bmp],[Size],Written,0
invoke CloseHandle,[F]
ret
endp
invoke CreateDC,"DISPLAY",0,0,0
mov [DC],eax
invoke CreateCompatibleDC,[DC]
mov [CDC],eax
mov [Bih.biSize],44
mov eax,[_Width]
mov [Bih.biWidth],eax
mov eax,[_Height]
mov [Bih.biHeight],eax
mov [Bih.biPlanes],1
mov [Bih.biBitCount],24
mov [Size],3
mov eax,[Size]
imul eax,[_Width]
imul eax,[_Height]
mov [Size],eax
mov [Bfh.bfType],4D42h
mov [Bfh.bfOffBits],64
mov [BmpInfo],Bih
invoke CreateDIBSection,[DC],[BmpInfo],0,Bmp,0,0
mov [CBmp],eax
invoke SelectObject,[CDC],[CBmp]
invoke GetSystemMetrics,SM_CXSCREEN
mov [ResolutionX],eax
invoke GetSystemMetrics,SM_CYSCREEN
mov [ResolutionY],eax
invoke StretchBlt,[CDC],0,0,[_Width],[_Height],[DC],0,0,[ResolutionX],[ResolutionY],SRCCOPY
invoke CreateFile,[_FileName],GENERIC_WRITE,0,0,CREATE_ALWAYS,0,0
mov [F],eax
invoke WriteFile,[F],Bfh,20,Written,0
invoke WriteFile,[F],Bih,44,Written,0
invoke WriteFile,[F],[Bmp],[Size],Written,0
invoke CloseHandle,[F]
ret
endp
Дело в том, что я в дельфях не шарю вообще так что если я допустил какую-то ошибку - подправьте.
Код на астме сохраняет битмап в фай но с кривым заголовком (т.е. не правильным). И даже когда вручную создать заголовок для битмапа и наконец увидеть сделанный скрин, то оказываеться и битмап не правильный: верхняя часть скрина (пол екрана) с зеленоватым оттенком, а нижняя абсолютно нормальная.
Код на FASM'е
Код:
include '..\..\INCLUDE\win32ax.inc'
.data
Bih BITMAPINFOHEADER
Bfh BITMAPFILEHEADER
CDC dd ?
DC dd ?
CBmp dd ?
Bmp dd ?
BmpInfo dd ?
F dd ?
Size dd ?
Written dd ?
ResolutionX dd ?
ResolutionY dd ?
.code
start:
stdcall ScreenShot,1280,1024,"C:\screenshot.bmp"
invoke ExitProcess, 0
proc ScreenShot, _Width, _Height, _FileName
invoke CreateDC,"DISPLAY",0,0,0
mov [DC],eax
invoke CreateCompatibleDC,[DC]
mov [CDC],eax
mov [Bih.biSize],40
mov eax,[_Width]
mov [Bih.biWidth],eax
mov eax,[_Height]
mov [Bih.biHeight],eax
mov [Bih.biPlanes],1
mov [Bih.biBitCount],24
mov [Size],3
mov eax,[Size]
imul eax,[_Width]
imul eax,[_Height]
mov [Size],eax
mov [Bfh.bfType],4D42h
mov [Bfh.bfOffBits],58
mov [BmpInfo],Bih
invoke CreateDIBSection,[DC],[BmpInfo],0,Bmp,0,0
mov [CBmp],eax
invoke SelectObject,[CDC],[CBmp]
invoke GetSystemMetrics,SM_CXSCREEN
mov [ResolutionX],eax
invoke GetSystemMetrics,SM_CYSCREEN
mov [ResolutionY],eax
invoke StretchBlt,[CDC],0,0,[_Width],[_Height],[DC],0,0,[ResolutionX],[ResolutionY],SRCCOPY
invoke CreateFile,[_FileName],GENERIC_WRITE,0,0,CREATE_ALWAYS,0,0
mov [F],eax
invoke WriteFile,[F],Bfh,14,Written,0
invoke WriteFile,[F],Bih,44,Written,0
invoke WriteFile,[F],[Bmp],[Size],Written,0
invoke CloseHandle,[F]
ret
endp
.end start
.data
Bih BITMAPINFOHEADER
Bfh BITMAPFILEHEADER
CDC dd ?
DC dd ?
CBmp dd ?
Bmp dd ?
BmpInfo dd ?
F dd ?
Size dd ?
Written dd ?
ResolutionX dd ?
ResolutionY dd ?
.code
start:
stdcall ScreenShot,1280,1024,"C:\screenshot.bmp"
invoke ExitProcess, 0
proc ScreenShot, _Width, _Height, _FileName
invoke CreateDC,"DISPLAY",0,0,0
mov [DC],eax
invoke CreateCompatibleDC,[DC]
mov [CDC],eax
mov [Bih.biSize],40
mov eax,[_Width]
mov [Bih.biWidth],eax
mov eax,[_Height]
mov [Bih.biHeight],eax
mov [Bih.biPlanes],1
mov [Bih.biBitCount],24
mov [Size],3
mov eax,[Size]
imul eax,[_Width]
imul eax,[_Height]
mov [Size],eax
mov [Bfh.bfType],4D42h
mov [Bfh.bfOffBits],58
mov [BmpInfo],Bih
invoke CreateDIBSection,[DC],[BmpInfo],0,Bmp,0,0
mov [CBmp],eax
invoke SelectObject,[CDC],[CBmp]
invoke GetSystemMetrics,SM_CXSCREEN
mov [ResolutionX],eax
invoke GetSystemMetrics,SM_CYSCREEN
mov [ResolutionY],eax
invoke StretchBlt,[CDC],0,0,[_Width],[_Height],[DC],0,0,[ResolutionX],[ResolutionY],SRCCOPY
invoke CreateFile,[_FileName],GENERIC_WRITE,0,0,CREATE_ALWAYS,0,0
mov [F],eax
invoke WriteFile,[F],Bfh,14,Written,0
invoke WriteFile,[F],Bih,44,Written,0
invoke WriteFile,[F],[Bmp],[Size],Written,0
invoke CloseHandle,[F]
ret
endp
.end start
Ошибка была втом, что я не правильно задал размеры обеих структур. Оказываеться, что размеры меньше на шесть байт.
вот только когда пишешь на асме врядли когда может пригодиться сохранять скриншот в файл