Capture d'écran sous windows

Résolu
D_A_R_K_O_S Messages postés 98 Date d'inscription vendredi 1 février 2013 Statut Membre Dernière intervention 23 juin 2015 - 23 mars 2014 à 21:32
D_A_R_K_O_S Messages postés 98 Date d'inscription vendredi 1 février 2013 Statut Membre Dernière intervention 23 juin 2015 - 7 avril 2014 à 18:17
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

cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
24 mars 2014 à 10:19
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
0
D_A_R_K_O_S Messages postés 98 Date d'inscription vendredi 1 février 2013 Statut Membre Dernière intervention 23 juin 2015
24 mars 2014 à 17:39
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 .
0
cptpingu Messages postés 3837 Date d'inscription dimanche 12 décembre 2004 Statut Modérateur Dernière intervention 28 mars 2023 123
Modifié par cptpingu le 24/03/2014 à 17:47
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
0
D_A_R_K_O_S Messages postés 98 Date d'inscription vendredi 1 février 2013 Statut Membre Dernière intervention 23 juin 2015
24 mars 2014 à 18:36
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.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
yann_lo_san Messages postés 1137 Date d'inscription lundi 17 novembre 2003 Statut Membre Dernière intervention 23 janvier 2016 26
26 mars 2014 à 13:58
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...
0
D_A_R_K_O_S Messages postés 98 Date d'inscription vendredi 1 février 2013 Statut Membre Dernière intervention 23 juin 2015
31 mars 2014 à 16:06
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 !
0
yann_lo_san Messages postés 1137 Date d'inscription lundi 17 novembre 2003 Statut Membre Dernière intervention 23 janvier 2016 26
1 avril 2014 à 14:13
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...
0
yann_lo_san Messages postés 1137 Date d'inscription lundi 17 novembre 2003 Statut Membre Dernière intervention 23 janvier 2016 26
1 avril 2014 à 14:30
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...
0
D_A_R_K_O_S Messages postés 98 Date d'inscription vendredi 1 février 2013 Statut Membre Dernière intervention 23 juin 2015
7 avril 2014 à 18:17
A oui, merci ça marche !
0
Rejoignez-nous