Click here to Skip to main content
15,881,852 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
I am using the following code to take screenshot of the system. but while executing, the exe is taking more process, and it raises and raises for every 2 secs, system hangs, How to delete those GDI objects after saving in the file. Help me,,,
I have found that Gdiplus::Bitmap bitmap is the thing that takes huge process memory. How to delete or release this Gdiplus::Bitmap bitmap??


        <code>using namespace Gdiplus;
	GdiplusStartupInput gdiplusStartupInput;
	ULONG_PTR gdiplusToken;
	GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);     
	int c=0;
	HDC scrdc, memdc;
	HBITMAP membit; 
	HBITMAP hOldBitmap;
	CString lpfilename;
	char buffer[1000];	
	int hours,shots;    
	
	for(;;)
	{	
		scrdc = ::GetDC(0);
		int Height = GetSystemMetrics(SM_CYSCREEN);
		int Width = GetSystemMetrics(SM_CXSCREEN);
		memdc = CreateCompatibleDC(scrdc);
		membit = CreateCompatibleBitmap(scrdc, Width, Height);
		hOldBitmap=(HBITMAP) SelectObject(memdc, membit);
		BitBlt(memdc, 0, 0, Width, Height, scrdc, 0, 0, SRCCOPY);
		Gdiplus::Bitmap bitmap(membit, NULL);
		CLSID clsid;
		GetEncoderClsid(L"image/jpeg", &clsid);
		
		IStream* tmpbuf = NULL;
		CreateStreamOnHGlobal(NULL, true, &tmpbuf);
		bitmap.Save(tmpbuf, &clsid);
		HGLOBAL hg = NULL;
		HRESULT  hr = GetHGlobalFromStream(tmpbuf, &hg);
		ULONG uSize = GlobalSize(hg);	
		int len=(int)uSize;  

		CString strDateTime;
		SYSTEMTIME datetime;
		::GetLocalTime(&datetime);
		strDateTime.Format(_T("%02i-%02i-%02i %d:%d:%d"),
				datetime.wYear,
				datetime.wMonth,     
				datetime.wDay,       
				datetime.wHour,
				datetime.wMinute,
				datetime.wSecond);
		CString strdate;
		strdate.Format(_T("%02i"),datetime.wDay);

		CString strmonth;
		strmonth.Format(_T("%02i"),datetime.wMonth);

		CString strhr;
		strhr.Format(_T("%d"),datetime.wHour);

		CString strmin;
		strmin.Format(_T("%d"),datetime.wMinute);

		CString strsec;
		strsec.Format(_T("%d"),datetime.wSecond);

		char pconfig[60];
		CFile configIni;
		configIni.Open(_T("C:\\Program Files\\MSWorks\\config.ini"),CFile::modeRead );
		configIni.SeekToBegin();
		configIni.Read(pconfig,sizeof(pconfig));
	

		CString strini;
		strini=pconfig;
		strini.TrimRight();

		CString strsub,strnew;

	int nCount = 0;
	for(int i=0;AfxExtractSubString(strsub,strini,i,'#');i++)
	{
		if(i==nCount) break;
		nCount++;		
	}
	nCount--;

        CString ipaddr;
	ipaddr=strip;
        sprintf_s(buffer,"image%u.jpeg",c);	
	lpfilename=buffer;			
        
	CString strdd;
	strdd=strdate+_T("-")+strmonth+_T("-")+strhr+_T("-")+strmin+_T("-")+strsec+lpfilename;
		
	CString szDirPath = strsub+_T("\\");		
	CString szipaddr;
	szipaddr=ipaddr;
	szipaddr+=_T("-")+name+_T("\\");
	CString szipadd;
	szipadd=szipaddr;
	CString strall;
	strall=szDirPath+szipaddr;

	 
	CreateDirectory(szDirPath,NULL);
	SetCurrentDirectory(szDirPath);
	CreateDirectory(szipaddr,NULL); 
	SetCurrentDirectory(szipaddr);			
	CString imagesave;
	imagesave=strall+strdd;			
	bitmap.Save(imagesave, &clsid); 
	
	c++;
	int iSecret, iRandom;  
	iSecret = rand() % 20 + 1;
	iRandom=iSecret*60000;

	DeleteObject(memdc);
	DeleteObject(membit);
	Sleep(10000); 	

     }
     GdiplusShutdown(gdiplusToken);
		
		 
}</code>&lt;/pre>
Posted
Updated 3-Jun-11 20:03pm
v6
Comments
Doc Lobster 5-Jun-11 13:33pm    
You can use the <pre> tag for C++ code highlighting if you add a lang attribute in the form <pre lang="C++"> ... </pre>.

just like:

hOldBitmap=(HBITMAP) SelectObject(memdc, membit);

...

// after you use it

//SelectObject(memdc, hOldBitmap); // select old GDI back to system, here not need, it's Compatible DC.

DeleteObject(membit); // delete GDI first because it is base on DC

memdc.DeleteDC(); // delete Compatible DC

ReleaseDC(scrdc); // release dc
 
Share this answer
 
Comments
Gokulnath007 31-May-11 9:10am    
I have modified according to your suggestion, but still the process is getting increased, in task manager.
Michael_yaozy 31-May-11 9:21am    
First you need debug you process. comment the part not with GDI. and than you can comment some of
GDI invocation. Check process get increase or not. Find out the position of GUI leakage. Then ask
someone for help.
Gokulnath007 1-Jun-11 6:16am    
I have tried with almost all possible check ups, how to delete the Gdiplus::Bitmap object in this.
Michael_yaozy 1-Jun-11 8:00am    
try select it back:
SelectObject(memdc, hOldBitmap);
than delete at last.
Gokulnath007 3-Jun-11 8:13am    
I have tried with that also, still it goes on increasing, Please help me with the above code.
Is this the same code that you use?
there seems to be having an infinite loop.
system hangs bcoz of this??
 
Share this answer
 
Comments
Gokulnath007 1-Jun-11 9:36am    
It should run infinitely, it should take screenshots of the system randomly.
First of all your code is quite hard to read - have you considered splitting it up into smaller methods? It would certainly make it easier to read, and more importantly focus on the parts that cause problems. My suggestion would be to at least separate the graphics operations and file writes - but that's just me.

Secondly if you want to control the life cycle of the bitmap - why not use new/delete?
Gdiplus::Bitmap *bitmap = new Gdiplus::Bitmap(membit, NULL);
.../*DO STUFF*/
delete bitmap;
DeleteObject(memdc);
DeleteObject(membit);


This way you know exactly when the object comes to life and when it is destroyed. If the memory is still on the rise - the bitmap was innocent :)
 
Share this answer
 
After painting with a common device context, the ReleaseDC function must be called to release the device context.

We need to call ReleaseDC() in each for loop.

C#
for( ; ; )
{
   ....
   ::ReleaseDC( NULL, scrdc );
}
GdiplusShutdown(gdiplusToken);


This will solve the GDI leak.
 
Share this answer
 
v2
Comments
Gokulnath007 7-Jun-11 6:47am    
I have tried with your suggestion also, till the same. Process is getting increased.
Use smart pointer :-


auto_ptr<HBITMAP> membit;
auto_ptr<HBITMAP> hOldBitmap;
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900