Newsgroup: it.comp.programmare.win32
Titolo: Eseguire screenshot

Salve,
sapreste dirmi se c'è un API per cattuarare lo screenshot dello schermo?
O magari qualche API per eseguire la pressione del tasto Stamp, anche se in 
questo caso poi dovrei anche occuparmi di incollare l'immagine da qualche 
parte.
Grazie 

Noixe ha scritto:

Estrapolato da mie librerie, ho lasciato solo la classe P_File, ma è 
semplice usare un altro metodo per il salvataggio (sempre che occorra 
salvarlo su file).
La prima parte cattura il desktop, la seconda estrai i byte.
Non ritestato.
Ciao
<code>
//----------------------------------------------------------------------------
static bool saveImageScreen(LPCTSTR filename)
{
   HDC hdc = GetDC(NULL);
   uint w = GetSystemMetrics(SM_CXSCREEN);
   uint h = GetSystemMetrics(SM_CYSCREEN);
   HBITMAP hBmp = CreateCompatibleBitmap(hdc, w, h);
   HDC mdc = CreateCompatibleDC(hdc);
   HGDIOBJ oldObj = SelectObject(mdc, hBmp);
   BitBlt(mdc, 0, 0, w, h, hdc, 0, 0, SRCCOPY);
   SelectObject(mdc, oldObj);
   DeleteDC(mdc);
   BITMAP bmp;
   GetObject((HGDIOBJ)hBmp, sizeof(bmp), &bmp);
   BITMAPFILEHEADER bmfh;
   DWORD image_length = ((bmp.bmWidth * 3 + 3) & ~3) * bmp.bmHeight;
   memcpy (&bmfh.bfType, "BM", 2);
   bmfh.bfReserved1 = 0;
   bmfh.bfReserved2 = 0;
   bmfh.bfSize = LEN_BMPFILEHEADER + sizeof(BITMAPINFOHEADER) + 
image_length;
   bmfh.bfOffBits = LEN_BMPFILEHEADER + sizeof(BITMAPINFOHEADER);
   P_File f(filename, P_CREAT);
   bool success = false;
   do {
     if(!f.P_open())
       break;
     if(LEN_BMPFILEHEADER != f.P_write(&bmfh, LEN_BMPFILEHEADER))
       break;
     BITMAPINFOHEADER bmih;
     memset(&bmih, 0, sizeof(bmih));
     bmih.biSize = sizeof(BITMAPINFOHEADER);
     bmih.biWidth = bmp.bmWidth;
     bmih.biHeight = bmp.bmHeight;
     bmih.biPlanes = bmp.bmPlanes;
     bmih.biBitCount =  24;//(WORD)(bmp.bmPlanes * bmp.bmBitsPixel);
     bmih.biCompression = BI_RGB;
     bmih.biSizeImage = image_length;
     if(sizeof(bmih) != f.P_write(&bmih, sizeof(bmih)))
       break;
     LPBYTE pBits = new BYTE[image_length + 2];
     GetDIBits(hdc, hBmp, 0L, (DWORD)bmih.biHeight, pBits, 
(LPBITMAPINFO)&bmih, (DWORD)DIB_RGB_COLORS);
     success = image_length == f.P_write(pBits, image_length);
     delete []pBits;
     } while(false);
   ReleaseDC(NULL, hdc);
   DeleteObject(hBmp);
   return success;
}
//----------------------------------------------------------------------------
</code>

In rete ho trovato un codice per C++ builder abbastanza semplice, che ho un 
po' adattato:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    TImage *ScreenShot = new TImage(this);
    TCanvas *AreaDesktop = new TCanvas();
    AreaDesktop->Handle = GetWindowDC(GetDesktopWindow());
    ScreenShot->Width = Screen->Width;
    ScreenShot->Height = Screen->Height;
    ScreenShot->Canvas->CopyRect(AreaDesktop->ClipRect, AreaDesktop, 
AreaDesktop->ClipRect);
    ScreenShot->Picture->SaveToFile("Desktop.bmp");
    ReleaseDC(GetDesktopWindow(), AreaDesktop->Handle);
    delete ScreenShot;
    delete AreaDesktop;
}
Però crea file da 3MB. Qualcuno conosce un modo per far si che l'immagine 
creata sia una jpeg?
Grazie 

Noixe ha scritto:

prova a cercare il componente TJPEGImage.
Oppure cerca i sorgenti e/o dll del jpeg e usi la parte di codice che 
avevo postato per ottenere i byte dell'immagine.
Ciao

 prova a cercare il componente TJPEGImage.
Ne ho trovata una versione per Delphi.
C++ builder 3 non ha tale componente, forse si trova nelle versioni 
successive? 

 prova a cercare il componente TJPEGImage.
Ok trovato grazie per le informazioni. 

Il codice che uso è il seguente:
TImage* ScreenShot = new TImage(this);
TCanvas* AreaDesktop = new TCanvas();
AreaDesktop->Handle = GetWindowDC(GetDesktopWindow());
ScreenShot->Width = Screen->Width;
ScreenShot->Height = Screen->Height;
ScreenShot->Canvas->CopyRect(AreaDesktop->ClipRect, AreaDesktop, 
AreaDesktop->ClipRect);
TJPEGImage* JpegImg = new TJPEGImage();
JpegImg->Assign(ScreenShot->Picture->Bitmap);
JpegImg->SaveToFile("ss.jpg");
ReleaseDC(GetDesktopWindow(), AreaDesktop->Handle);
delete ScreenShot;
delete AreaDesktop;
delete JpegImg;
Per caso c'è quache proprietà da leggere per rilevare la dimensione del file 
jpeg?
Ho notato che a differenza delle bitmap, le jpeg di volta in volta hanno 
dimensioni diverse, in base al contenuto dello screenshot stesso, per cui 
per quello che devo fare io, posso sfruttare tale caratteristica per evitare 
screenshot doppioni. C'è qualche metodo apposta oppure devo utilizzare 
funzioni generiche per file qualsiasi? 

 utilizzare funzioni generiche per file qualsiasi?
Ho risolto con la funzione
int filelength(int handle);