[Delphi] Screenshot w WinApi

0

witam ;)

chodzi o screenshota, oczywiscie progs musi sie zmiescic w ~20 kB wiec..

wymsylilem symulaje wcisniecia klawisza printscreen, pobranie SSa ze schowka i zapisanie go, ale... do takiej operacji uzylem modulu Graphics, gdyz w nim jest lastwa mozliwosc operacja na bitmapach. taki mogol to +200 kB wiec nie za dobrze -.-

inny sposob, o ile pamietam to mozna zrobic cos w stylu

var
  h, d, p: HDC;

begin
  h := CreateDC('DISPLAY', Nil, Nil, Nil);
  d := CreateCompatibleDC(h);
  p := CreateCompatibleBitmap(h, GetDeviceCaps(h, HORZRES), GetDeviceCaps(h, VERTRES));
  SelectObject(d, p);
  BitBlt(d, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), h, 0, 0, SRCCOPY);
end;

ale jak to zapisac do pliku? ;>

moze byc kazdy inny sposob ktory malo zajmuje.. np. otwieranie paina, wklejanie bitmapy i zapisywanie -.-

hwo to? ;>

0

Znów trojan? Poprzednio pobieranie execa z www w 50KB... Jak zapisać do pliku? Normanie, robisz plik bmp i zapisujesz - wypełniasz odpowiednie nagłówki i tyle. A... Tobie potrzebny screenshot w jpg, nie? :>

0

nie prosciej skopiować z Graphics to co potrzebujesz?
Kiedyś robiłem coś takiego z Reigstry.
Cały unit: 50kb.
Po wybraniu tego co potrzeba miałem tylko +5kb ;p

0

oj deus deus i te twoje trojany ;) ja <ort>po prostu</ort> pisze male, bardzo.. programy, VCL to lamerskie -.- a coz.. tego akurat nie wiem, jpg - nie koniecznie...

Jak zapisać do pliku? Normanie, robisz plik bmp i zapisujesz - wypełniasz odpowiednie nagłówki i tyle

kk, robie plik bmp, czyli pusty z rozszerzeniem bmp? -.- no jest.. i zapisuje, co zapisuje? oO mam tylko wskaznik (chyba) 1 bajta tej grafiki, wypelniam naglowki? polacz to w calosc i zastanow sie co ty gadasz -.-

// co gadam? dokładnie to, co reichel podał w swoim przykładzie, skoro nie rozumiesz to Twój problem. (dop. deus)

@djmentos: tam jest 7300 lini -.- to ew. bedzie ostatecznosc

czyli nikt nie umie? ;)

0

Kod w c++, pozmaieniaj = na :=, wskazniki & na @ etc...

albo poczytaj o GetDIBits na MSDN

//Można użyć w C bezpośrednio gdyż nie zastosowałem
//klasy CBitmap oraz strumieni do zapisu plikó.
void  SaveBitmap(wchar_t *szFilename,HBITMAP hBitmap)

{

      HDC dc;
      FILE* fp;
      LPVOID pBuf = NULL;
      BITMAPINFO BI;//Struktura zawierająca opis bitmapy (kolor etc)
      BITMAPFILEHEADER  BFH; //Struktura związana z opisem nagłówka WindowsBitmap

//pobieramy kontekst w przypadku gdy parametr równy jest NULL
//pobrany zostanie kontekst całego ekranu.
      dc = GetDC(NULL);
      ZeroMemory(&BI,sizeof(BITMAPINFO));
//rozmiar powinien być taki jak rozmiar struktury
//(dzięki temu można rozpoznać wersje).
      BI.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
//Funkcja GetDIBits gdy parametr lvpBits jest róny NULL
//zwraca liczbę ScanLines (nie mam pojęcia jak to przetłumaczyć)
//Dzieki tym informacją możliwe jest zaalokowanie odpowiedniej
//pamięci dla bitmapy.

      GetDIBits(dc,hBitmap,0,0,NULL,&BI,DIB_RGB_COLORS); 

//Gdy to pole nie ustawione lub mniejsze od zera, należy
//samemu obliczyć rozmiar bitmapy na podstawie wysokości,
//szerokości oraz liczby kolorów.
         if(BI.bmiHeader.biSizeImage<=0)
              BI.bmiHeader.biSizeImage=BI.bmiHeader.biWidth*abs(BI.bmiHeader.biHeight)*(BI.bmiHeader.biBitCount+7)/8;

//teraz już można przydzielić pamięć dla bitmapy
      if((pBuf = malloc(BI.bmiHeader.biSizeImage))==NULL)
      {
        MessageBoxW( NULL, L"Nie można alokować pamięci", L"Błąd", MB_OK | MB_ICONERROR);
        return;
      }            
//wybieramy brak kompresji - bitmapa zapisana jako liczby opisujące kolor RGB
            BI.bmiHeader.biCompression=BI_RGB;
//w tym przypadku wywołanie funkcji z parametrem lvpBits 
//jako przydzielony obszar pamięci: pBuf
//zwróci dane opisujące obraz z uchwytu bitmapy hBitmap do pBuf.
      GetDIBits(dc,hBitmap,0,BI.bmiHeader.biHeight,pBuf, &BI, DIB_RGB_COLORS);       
//
      if((_wfopen_s(&fp,szFilename,L"wb"))!= 0 )
      {
	  //bardziej kulturalne było by zrealizowanie tego za pomocą wyjątków
	   if (dc)  ReleaseDC(NULL,dc); 
	   if (pBuf) free(pBuf); 
       MessageBoxW( NULL, L"Nie można utworzyć bitmapy", L"Błąd", MB_OK | MB_ICONERROR);
       return;
      } 

	//rozmiar pliku
      BFH.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+BI.bmiHeader.biSizeImage;
//początek pliku zaczyna się od znakó BM, notacja związana z zapisem liczb
      BFH.bfType='MB';
//miejsce od kiedy zaczynają się dane opisujące obraz
      BFH.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER); 
//zapis do pliku
      fwrite(&BFH,sizeof(BITMAPFILEHEADER),1,fp);
      fwrite(&BI.bmiHeader,sizeof(BITMAPINFOHEADER),1,fp);
      fwrite(pBuf,BI.bmiHeader.biSizeImage,1,fp); 
      
//zwalniamy zasoby i zamykamy pliki
      if (dc)  ReleaseDC(NULL,dc); 
      if (pBuf) free(pBuf); 
      if (fp)   fclose(fp);
}

0

cos takiego? ;>

var
  dc: HDC;
  fp: File;
  pBuf: LPARAM;
  BI: BITMAPINFO;
  BFH: BITMAPFILEHEADER;
  bitmp: HBITMAP;

begin
  dc := GetDC(0);
  ZeroMemory(@BI, SizeOf(BITMAPINFO));

  BI.bmiHeader.biSize := SizeOf(BITMAPINFOHEADER);

  GetDIBits(dc, bitmp, 0, 0, Nil, BI, DIB_RGB_COLORS); //-

  if BI.bmiHeader.biSizeImage <= 0 then
    BI.bmiHeader.biSizeImage := BI.bmiHeader.biWidth*abs(BI.bmiHeader.biHeight)*(BI.bmiHeader.biBitCount+7) div 8;

  // przydzielanie pamieci -> if pBuf = malloc(BI.bmiHeader.biSizeImage)

  BI.bmiHeader.biCompression := BI_RGB;

  GetDIBits(dc, bitmp, 0, BI.bmiHeader.biHeight, @pBuf, BI, DIB_RGB_COLORS);

  BFH.bfSize := SizeOf(BITMAPFILEHEADER)+SizeOf(BITMAPINFOHEADER)+BI.bmiHeader.biSizeImage;
  BFH.bfType := 1;
  BFH.bfOffBits := SizeOf(BITMAPFILEHEADER)+SizeOf(BITMAPINFOHEADER);

  assignfile(fp, 'C:\test.bmp');
  rewrite(fp);

  BlockWrite(fp, BFH, SizeOf(BITMAPFILEHEADER));
  BlockWrite(fp, BI, SizeOf(BITMAPINFOHEADER));
  BlockWrite(fp, pBuf, BI.bmiHeader.biSizeImage);

  CloseFile(fp);
  ReleaseDC(0, dc);
end.

bo to niedziala ;P tworzy plik bitmapy wypelniony nullami.. tylko naglowki sa

0

Prawie ........ zanim zabierzesz sie za nastepny projekt poczytaj ....

jesli jest BFH.bfType ='MB' to dlaczego piszesz BFH.bfType = 1. Jakby takie elementy nie byly istotne to by ich nie bylo ....

poprawiony kod

var
  dc: HDC;
  fp: File;
  pBuf: PChar;
  BI: BITMAPINFO;
  BFH: BITMAPFILEHEADER;
  bitmp: HBITMAP;

var
  h, d: HDC;

begin
  h := GetDC(0);
  d := CreateCompatibleDC(h);
  bitmp := CreateCompatibleBitmap(h, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
  SelectObject(d, bitmp);
  BitBlt(d, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), h, 0, 0, SRCCOPY);

  dc := GetDC(0);
  ZeroMemory(@BI, SizeOf(BITMAPINFO));

  BI.bmiHeader.biSize := SizeOf(BITMAPINFOHEADER);

  GetDIBits(dc, bitmp, 0, 0, Nil, BI, DIB_RGB_COLORS); //-

  if BI.bmiHeader.biSizeImage <= 0 then
    BI.bmiHeader.biSizeImage := BI.bmiHeader.biWidth*abs(BI.bmiHeader.biHeight)*(BI.bmiHeader.biBitCount+7) div 8;

  GetMem(pBuf,BI.bmiHeader.biSizeImage);

  BI.bmiHeader.biCompression := BI_RGB;

  GetDIBits(dc, bitmp, 0, BI.bmiHeader.biHeight, pBuf, BI, DIB_RGB_COLORS);

  BFH.bfSize := SizeOf(BITMAPFILEHEADER)+SizeOf(BITMAPINFOHEADER)+BI.bmiHeader.biSizeImage;
  BFH.bfType := ord('M')shl 8 or ord('B');
  BFH.bfOffBits := SizeOf(BITMAPFILEHEADER)+SizeOf(BITMAPINFOHEADER);

  assignfile(fp, 'C:\test.bmp');
  rewrite(fp,1);

  BlockWrite(fp, BFH, SizeOf(BITMAPFILEHEADER));
  BlockWrite(fp, BI, SizeOf(BITMAPINFOHEADER));
  BlockWrite(fp, pBuf^, BI.bmiHeader.biSizeImage);

  CloseFile(fp);
  ReleaseDC(0, dc);
  FreeMem(pBuf);

end;
0

dziala, dzieki za kod ;) wlasnie niewedzialem co zrobic z tym "Type" -> "MB"

ale.. ten kod ort! SSa elementow polprzezroczystych, tj. tych co uzywaja AlphaBlend, oraz filmow, gier etc..

wiec

var
  r: TRect;

begin
  keybd_event(44, 0, 0, 0); // print screen
  sleep(1000);
  GetWindowRect(GetDesktopWindow, r); // pobieranie rozdzielczosci
(...)
end;

teraz SS jest w schowku, jak go wyjac i zapisac? ;)

0

zapewne bedzie trzba zastosowac funkcje
GetClipboardData
http://msdn2.microsoft.com/en-us/library/ms649039.aspx

z parametrem CF_BITMAP i zastosowac kawalek (zapis) powyzszego kodu.

UWAGA!!!
Uprzedzam problemy, ktore moga sie pojawic. Zapis ktory przedstawilem nie uwzglednia wszystkich mozliwych bitmap, zatem lepiej zlapac bitmape ze schowka, pobrac jej wymiary, stworzyc nowa, skopiowac. I nie stosowac CreateCompatibleBitmap, a tworzyc bitmape taka jaka chcemy (zakladajac, ze program przelacza nas w tryb 16 kolorow). Ale o tym poczytaj bo nikt nie bedzie robil specjalnie dla ciebie wykladu.

che che poza tym printscreen mozna zablokowac ... i pewnie robia to niektore gry, odtwarzacze filmow
tu taka najnajprostsza metoda
Jak zablokować klawisz Print Screen

0

no to zostane przy tej metodzie... chociaz u mnie np. nielapie paska zadan, ktory jest polprzezroczysty (vista inspirant)

jeszcze raz dzieki za pomoc ;)

1 użytkowników online, w tym zalogowanych: 0, gości: 1