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

D_A_R_K_O_S 104 Messages postés vendredi 1 février 2013Date d'inscription 23 juin 2015 Dernière intervention - 23 mars 2014 à 21:32 - Dernière réponse : D_A_R_K_O_S 104 Messages postés vendredi 1 février 2013Date d'inscription 23 juin 2015 Dernière intervention
- 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 ! :)
Afficher la suite 

Votre réponse

9 réponses

cptpingu 3827 Messages postés dimanche 12 décembre 2004Date d'inscriptionModérateurStatut 6 octobre 2018 Dernière intervention - 24 mars 2014 à 10:19
0
Merci
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
Commenter la réponse de cptpingu
D_A_R_K_O_S 104 Messages postés vendredi 1 février 2013Date d'inscription 23 juin 2015 Dernière intervention - 24 mars 2014 à 17:39
0
Merci
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 .
Commenter la réponse de D_A_R_K_O_S
cptpingu 3827 Messages postés dimanche 12 décembre 2004Date d'inscriptionModérateurStatut 6 octobre 2018 Dernière intervention - Modifié par cptpingu le 24/03/2014 à 17:47
0
Merci
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
Commenter la réponse de cptpingu
D_A_R_K_O_S 104 Messages postés vendredi 1 février 2013Date d'inscription 23 juin 2015 Dernière intervention - 24 mars 2014 à 18:36
0
Merci
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.
Commenter la réponse de D_A_R_K_O_S
yann_lo_san 1137 Messages postés lundi 17 novembre 2003Date d'inscription 23 janvier 2016 Dernière intervention - 26 mars 2014 à 13:58
0
Merci
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...
Commenter la réponse de yann_lo_san
D_A_R_K_O_S 104 Messages postés vendredi 1 février 2013Date d'inscription 23 juin 2015 Dernière intervention - 31 mars 2014 à 16:06
0
Merci
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 !
Commenter la réponse de D_A_R_K_O_S
yann_lo_san 1137 Messages postés lundi 17 novembre 2003Date d'inscription 23 janvier 2016 Dernière intervention - 1 avril 2014 à 14:13
0
Merci
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...
Commenter la réponse de yann_lo_san
yann_lo_san 1137 Messages postés lundi 17 novembre 2003Date d'inscription 23 janvier 2016 Dernière intervention - 1 avril 2014 à 14:30
0
Merci
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...
Commenter la réponse de yann_lo_san
D_A_R_K_O_S 104 Messages postés vendredi 1 février 2013Date d'inscription 23 juin 2015 Dernière intervention - 7 avril 2014 à 18:17
0
Merci
A oui, merci ça marche !
Commenter la réponse de D_A_R_K_O_S

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.