Salve.
Ho già cercato su questo forum e da altre parti, senza trovare una risposta soddisfacente: come fare uno screenshot funzionante di qualcosa?

Evitate per favore di suggerirmi freelibrary: il mio obiettivo è imparare e non fare (come ho già provato)

codice:
fipWinImage Img;
Img.capturewindow(GetDesktopWindow(),GetDesktopWindow());
Img.save("C:/Ciao.jpg",FIF_JPG);
Ci sono molte guide su come farlo in C#, che sostanzialmente ricalcano lo stesso codice che vedrete sotto, solo che arrivato ad avere un puntatore HBITMAP, usano la funzione Image::FromhBitmap e ha finito poichè la classe ha tutti i metodi necessari per salvare quest'ultima anche in altri formati.

Usando msdn e qualche altra referenza sono arrivato a scrivere questo codice

codice:
int MakeScreenShoot(void)
{
	HWND desktop = GetDesktopWindow();
	HDC ScreenDesktop = GetDC(desktop);

	int ResX = GetSystemMetrics(SM_CXSCREEN);
	int ResY = GetSystemMetrics(SM_CYSCREEN);

	HDC MemDesktop = CreateCompatibleDC(ScreenDesktop);
	HBITMAP tmpbitmap = CreateCompatibleBitmap(MemDesktop,ResX,ResY);

	HBITMAP bitmap = (HBITMAP)SelectObject(MemDesktop,tmpbitmap);


	BitBlt(MemDesktop,0,0,ResX,ResY,ScreenDesktop,0,0,SRCCOPY);
	
	BITMAPINFO BitInfo;

	memset(&BitInfo,0,sizeof(BITMAPINFO));

	BitInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	BitInfo.bmiHeader.biWidth = ResX;
	BitInfo.bmiHeader.biHeight = ResY;
	BitInfo.bmiHeader.biPlanes = 1;
	BitInfo.bmiHeader.biBitCount = 16;
	BitInfo.bmiHeader.biCompression = BI_RGB;
	BitInfo.bmiHeader.biSizeImage = (BitInfo.bmiHeader.biWidth * BitInfo.bmiHeader.biHeight) * 2;

	void *bits = malloc(BitInfo.bmiHeader.biSizeImage);
	GetDIBits(MemDesktop,bitmap,0,BitInfo.bmiHeader.biHeight,bits,&BitInfo,DIB_PAL_COLORS);
	HANDLE bmfile = CreateFile("C:\\image.bmp",GENERIC_READ | GENERIC_WRITE,NULL,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);

	BITMAPFILEHEADER bitheader;

	bitheader.bfReserved1 = 0;
	bitheader.bfReserved2 = 0;
	bitheader.bfType = 0x4d42;
	bitheader.bfOffBits = sizeof(BITMAPINFOHEADER) + sizeof(BITMAPFILEHEADER);
	bitheader.bfSize = bitheader.bfOffBits + BitInfo.bmiHeader.biSizeImage;

	DWORD bytes;

	WriteFile(bmfile,&bitheader,sizeof(BITMAPFILEHEADER),&bytes,NULL);
	WriteFile(bmfile,&BitInfo.bmiHeader,sizeof(BITMAPINFOHEADER),&bytes,NULL);
	WriteFile(bmfile,bits,BitInfo.bmiHeader.biSizeImage,&bytes,NULL);
	

	CloseHandle(bmfile);
	free(bits);
	DeleteDC(MemDesktop);
	ReleaseDC(desktop,ScreenDesktop);
	DeleteObject(bitmap);
	DeleteObject(tmpbitmap);

	return 0;

}
Una cosa non ho capito: perchè devo fare il SelectObject...a cosa serve fare l'associazione, dato che la copia mi sembra esser fatta in modo "raw" da BitBtl? Abilita lo scambio di dati? Ma poi, se la copia dei bit mi arriva su un puntatore che gli do stesso io, perchè mi chiede un'HBITMAP? Non ne capisco il senso: tra l'altro poi questa HBITMAP sembra servire solo a questo e a nient'altro: esser passata come parametro.

Apparte il fatto che l'unica cosa che vedo è una bitmap nera (anche se non riescoa capire ancora perchè), la mia intenzione sarebbe salvare almeno in jpg.
Sulla documentazione MSDN sembra che per fare ciò basta cambiare un flag e settare a 0 il valore bits per pixel.
Riporto il pezzo per intero
biCompression
Specifies the type of compression for a compressed bottom-up bitmap (top-down DIBs cannot be compressed). This member can be one of the following values.
biSizeImage
Specifies the size, in bytes, of the image. This may be set to zero for BI_RGB bitmaps.
Windows 98/Me, Windows 2000/XP: If biCompression is BI_JPEG or BI_PNG, biSizeImage indicates the size of the JPEG or PNG image buffer, respectively.
Cosa significa il remark del secondo parametro? Che dimensione gli devo mettere? La massima che voglio poi sarà lui a regolarsi su come fare il controllo qualità?
Ad ogni modo, scrivendo con lo stesso codice, almeno usando bitmap si vedeva nero, qui invece la da proprio come file corrotto.
Avete qualche idea su come fare?