Capture d'écran sous windows [Résolu]

Signaler
Messages postés
98
Date d'inscription
vendredi 1 février 2013
Statut
Membre
Dernière intervention
23 juin 2015
-
Messages postés
98
Date d'inscription
vendredi 1 février 2013
Statut
Membre
Dernière intervention
23 juin 2015
-
Bonjour,
J'aimerais dans mon programme en C récupérer une image de ce qui est affiché à l'écran de l'utilisateur, exactement comme quand on appuie sur le bouton "imprécr".
Est-ce possible ? Je code sous windows avec code::block, et utilise la SDL.

Merci d'avance pour vos éventuelles réponse ! :)

9 réponses

Messages postés
3839
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
15 avril 2021
121
Bonjour.

Une petite recherche sur "SDL screenshot", t'aurais emmené ici:
https://stackoverflow.com/questions/20233469/how-do-i-take-and-save-a-bmp-screenshot-in-sdl-2

__________________________________________________________________________________________________
Améliorez votre expérience CodeS-SourceS avec ce plugin:
http://codes-sources.commentcamarche.net/forum/affich-10000111-plugin-better-cs-2#cptpingu-signature
Messages postés
98
Date d'inscription
vendredi 1 février 2013
Statut
Membre
Dernière intervention
23 juin 2015

Salut
Merci de la réponse, mais de ce que j'ai compris cela permet de récupérer une impression d'écran de la fenêtre de notre programme. Je me suis peut être mal exprimé : j'aimerais récupérer une image de l'ensemble de l'écran, y compris la barre des tâches et le fond d'écran si on le voit !
Je pense qu'il doit exister une fonction de windows.h mais je n'ai rien trouvé sur le site officiel http://msdn.microsoft.com/en-us/library .
Messages postés
3839
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
15 avril 2021
121
Au temps pour moi.
Dans ce cas, effectivement, tu ne peux pas le faire en SDL, puisqu'à ce niveau, tu es limité à ce que "voit" ton programme.
Il te faut donc réaliser un screenshot, en demandant à l'OS de le faire, mais j'ai du mal à en comprendre l'intérêt. Autant je vois les bénéfices de faire une capture d'écran sur son programme, qui plus est si c'est un jeu, autant je serais curieux de connaître ton besoin.

Réponse éventuelle à ta question:
https://stackoverflow.com/questions/997175/how-can-i-take-a-screenshot-and-save-it-as-jpeg-on-windows

__________________________________________________________________________________________________
Améliorez votre expérience CodeS-SourceS avec ce plugin:
http://codes-sources.commentcamarche.net/forum/affich-10000111-plugin-better-cs-2#cptpingu-signature
Messages postés
98
Date d'inscription
vendredi 1 février 2013
Statut
Membre
Dernière intervention
23 juin 2015

Merci de la réponse rapide,
Mon programme est simplement un entrainement qui ne me serrera sûrement jamais :p : c'est enfaîte un utilitaire qui prend des capture d'écrans toutes les X secondes pendant X secondes pour créer une explication d'une manipulation que l'ont envoie à la personne à aidée, un peu comme l'aide à distance de Windows !

Sinon je vais examiner les codes qu'il y a dans le lien pour voir si je peux les intégrer à mon programme.
Messages postés
1137
Date d'inscription
lundi 17 novembre 2003
Statut
Membre
Dernière intervention
23 janvier 2016
23
Salut,

en windows C / GDI :


VOID CopyFromScreen(HWND hWnd, LPTSTR strFileDest, int bmpWidth, int bmpHeight)
{
	HDC hdcScreen = ::CreateDC("DISPLAY", NULL, NULL, NULL); 
	HDC hdcCompatible = ::CreateCompatibleDC(hdcScreen); 
	HBITMAP hbmScreen = ::CreateCompatibleBitmap(hdcScreen, 
		::GetDeviceCaps(hdcScreen, HORZRES), 
		::GetDeviceCaps(hdcScreen, VERTRES)); 
	::SelectObject(hdcCompatible, hbmScreen);

         // masque appli en cours ou non
	//::ShowWindow(hwnd, SW_HIDE); 

	if(bmpWidth<=0)
		bmpWidth=::GetDeviceCaps(hdcScreen, HORZRES);
	if(bmpHeight<=0)
		bmpHeight = ::GetDeviceCaps(hdcScreen, VERTRES);

	::BitBlt(hdcCompatible, 
		0,0, 
		bmpWidth, bmpHeight, 
		hdcScreen, 
		0,0, 
		SRCCOPY);

             // reaffiche appli en cours ou non 
	//::ShowWindow(hwnd, SW_SHOW); 

        // Code pour créer le fichier BMP  (trop long pour mettre ici)
	/*
	CreateBMPFile(
		strFileDest, 
		CreateBitmapInfoStruct(hbmScreen), 
		hbmScreen, 
		hdcCompatible);
        */

	::ReleaseDC(hWnd,hdcCompatible);
	::DeleteDC(hdcScreen);
}



bye...
Messages postés
98
Date d'inscription
vendredi 1 février 2013
Statut
Membre
Dernière intervention
23 juin 2015

Justement comment fait tu pour générer le fichier BMP ? Sinon j'ai trouver des code qui y ressemble beaucoup mais le fichier bitmap généré est corrompu... Par contre le fond d'écran est bien dans le presse papier.
Je ne pensé pas que c'était si compliqué :) ! Je pense que je vais laisser ça de coté je réessayerais quand je connaîtrais mieux la programmation Windows. Merci quand même pour l'aide !
Messages postés
1137
Date d'inscription
lundi 17 novembre 2003
Statut
Membre
Dernière intervention
23 janvier 2016
23
Salut,

Voici les 2 fonctions que j'utilise pour générer le fichier dans l' appel a CopyFromScreen() :

void CreateBMPFile(LPTSTR pszFile, PBITMAPINFO pbi,  HBITMAP hBMP, HDC hDC) 
{ 
	 HANDLE hf;    
	 BITMAPFILEHEADER hdr;      
	 PBITMAPINFOHEADER pbih;  
	 LPBYTE lpBits;             
	 DWORD dwTotal;            
	 DWORD cb;                   
	 BYTE *hp;                   
	 DWORD dwTmp; 

	 pbih = (PBITMAPINFOHEADER) pbi; 
	 lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);

	 if (!lpBits) 
	     return; 

	 if (!GetDIBits(hDC, hBMP, 0, (WORD) pbih->biHeight, lpBits, pbi, 
	 DIB_RGB_COLORS)) 
	 {
	     return;
	 }

	 hf = CreateFile(pszFile, 
	     GENERIC_READ | GENERIC_WRITE, 
	     (DWORD) 0, 
	     NULL, 
	     CREATE_ALWAYS, 
	     FILE_ATTRIBUTE_NORMAL, 
	     (HANDLE) NULL); 
	 if (hf == INVALID_HANDLE_VALUE) 
	     return; 
	 hdr.bfType = 0x4d42;        // 0x42 = "B" 0x4d = "M" 
	 hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) + 
	 pbih->biSize + pbih->biClrUsed 
	     * sizeof(RGBQUAD) + pbih->biSizeImage); 
	 hdr.bfReserved1 = 0; 
	 hdr.bfReserved2 = 0; 

	 hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + 
	 pbih->biSize + pbih->biClrUsed 
	     * sizeof (RGBQUAD); 

	 if (!WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER), 
	 (LPDWORD) &dwTmp,  NULL)) 
	 {
	     return; 
	 }

	 if (!WriteFile(hf, (LPVOID) pbih, sizeof(BITMAPINFOHEADER) 
	 + pbih->biClrUsed * sizeof (RGBQUAD), 
	 (LPDWORD) &dwTmp, ( NULL))) 
	     return; 

	 dwTotal = cb = pbih->biSizeImage; 
	 hp = lpBits; 
	 if (!WriteFile(hf, (LPSTR) hp, (int) cb, (LPDWORD) &dwTmp,NULL)) 
	     return; 

	 if (!CloseHandle(hf)) 
	     return; 

	 GlobalFree((HGLOBAL)lpBits);
}

PBITMAPINFO CreateBitmapInfoStruct(HBITMAP hBmp)
{ 
	 BITMAP bmp; 
	 PBITMAPINFO pbmi; 
	 WORD    cClrBits;
	 if (!GetObject(hBmp, sizeof(BITMAP), &bmp)) 
		return NULL;

	 cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel); 
	 if (cClrBits == 1) 
	 cClrBits = 1; 
	 else if (cClrBits <= 4) 
	 cClrBits = 4; 
	 else if (cClrBits <= 8) 
	 cClrBits = 8; 
	 else if (cClrBits <= 16) 
	 cClrBits = 16; 
	 else if (cClrBits <= 24) 
	 cClrBits = 24; 
	 else cClrBits = 32; 

	 if (cClrBits != 24) 
	 pbmi = (PBITMAPINFO) LocalAlloc(LPTR, 
	 sizeof(BITMAPINFOHEADER) + 
	 sizeof(RGBQUAD) * (1<< cClrBits)); 
	 else 
	 pbmi = (PBITMAPINFO) LocalAlloc(LPTR, 
	 sizeof(BITMAPINFOHEADER)); 

	 pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 
	 pbmi->bmiHeader.biWidth = bmp.bmWidth; 
	 pbmi->bmiHeader.biHeight = bmp.bmHeight; 
	 pbmi->bmiHeader.biPlanes = bmp.bmPlanes; 
	 pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel; 
	 if (cClrBits < 24) 
	 pbmi->bmiHeader.biClrUsed = (1<<cClrBits); 

	 pbmi->bmiHeader.biCompression = BI_RGB; 

	 pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8
	 * pbmi->bmiHeader.biHeight; 
	 pbmi->bmiHeader.biClrImportant = 0; 
	 return pbmi; 
} 



bye...
Messages postés
1137
Date d'inscription
lundi 17 novembre 2003
Statut
Membre
Dernière intervention
23 janvier 2016
23
Re,

Si tu veux beaucoup plus simple,
il faut utiliser GDI +.

Voici le code pour créer un ScreenShot JPEG en GDIPlus


// init GDI+
#include <gdiplus.h>
using namespace Gdiplus;
#pragma comment(lib, "gdiplus.lib")

// Dans main
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;   
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

// crée le screenShot
Status status = CopyFromScreen(L"image/jpeg", L"monScreenShot.jpg", hWnd);

// Fin du main, libère gdi+
GdiplusShutdown(gdiplusToken);



Gdiplus::Status CopyFromScreen(const WCHAR* lpStrMimeType, const WCHAR* lpStrImageFileDest, HWND hwndHide)
{
	if(hwndHide != NULL)
		::ShowWindow(hwndHide, SW_HIDE);
	Gdiplus::Status status = Gdiplus::Status::GenericError;
	HDC hdcScreen = ::GetDC( 0 );
	int wdScreen = ::GetDeviceCaps(hdcScreen, HORZRES);
	int hgscreen = ::GetDeviceCaps(hdcScreen, VERTRES); 

	HDC memdc = ::CreateCompatibleDC(hdcScreen);
	HBITMAP membit = ::CreateCompatibleBitmap(hdcScreen, wdScreen, hgscreen);
	HBITMAP hOldBitmap =(HBITMAP)::SelectObject(memdc, membit);
	::BitBlt(memdc, 0, 0, wdScreen, hgscreen, hdcScreen, 0, 0, SRCCOPY);

	Bitmap bm(membit,(HPALETTE)NULL);
	CLSID clsid;
	if( GetEncoderClsid(lpStrMimeType, &clsid) >= 0 )
		status = bm.Save(lpStrImageFileDest, &clsid);

	::SelectObject(memdc, hOldBitmap);
	::DeleteObject(memdc);
	::DeleteObject(membit);
	::ReleaseDC(NULL,hdcScreen);

	if(hwndHide != NULL)
		::ShowWindow(hwndHide, SW_SHOW);

	return status;
}

/* Récupère un Clsid */
int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
{
	if( wcslen(format)==0 )
	{
		*pClsid = GUID_NULL;
		return -1;
	}

	UINT  num = 0;  
	UINT  size = 0; 
	ImageCodecInfo* pImageCodecInfo = NULL;
	GetImageEncodersSize(&num, &size);
	if(size > 0 && num > 0)
	{
		pImageCodecInfo = (ImageCodecInfo*)(::GlobalAlloc(0, size));
		if(pImageCodecInfo)
		{
			GetImageEncoders(num, size, pImageCodecInfo);
			for(UINT j = 0; j < num; ++j)
			{
				if( wcscmp(pImageCodecInfo[j].MimeType, format) == 0 )
				{
					*pClsid = pImageCodecInfo[j].Clsid;
					::GlobalFree(pImageCodecInfo);
					return j;
				}    
			}
			if(pImageCodecInfo)
				::GlobalFree(pImageCodecInfo);
		}
	}
	return -1;
}



bye...
Messages postés
98
Date d'inscription
vendredi 1 février 2013
Statut
Membre
Dernière intervention
23 juin 2015

A oui, merci ça marche !