BitBlt Error After Many Iterations

Hey guys,

I've ran into a bit of a snag... The program I'm writing captures a portion of my screen, stores it in memory, grabs pixel data from memory, then refreshes the screen capture.

Everything is working great UNTIL it reaches a large number of iterations (10,000) and then BitBlt begins throwing an error...

Using GetLastError(), I know the error code is 777AE010. Googling gave me literally no results. Literally only four links to nonsense pages. I downloaded the Microsoft Error Lookup Tool and it gave me the great description of:

Microsoft Windows [Version 10.0.19042.1165]
(c) Microsoft Corporation. All rights reserved.

C:\Users\**********>Downloads\Err_6.4.5.exe 777AE010
# Value 0x777ae010 is an NTSTATUS value: treating as 0x677ae010
# No results found for hex 0x677ae010 / decimal 1736106000
# NOT FOUND: 777AE010


So not even Microsoft knows the meaning behind their own error code.

Anyway, after several hours of Googling I think it's safe to say I'm reaching the limit of GDI Objects? After restarting the program, the error goes away until the limit is reached again.

Here is how I am managing the portion of code in question:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int get_Bitmap(int GxpSx, int GypSy, HDC& hdcMemory, int width, int height) { 
	HDC hdcSource = GetDC(NULL);													
	hdcMemory = CreateCompatibleDC(hdcSource);
	HBITMAP hBitmap = CreateCompatibleBitmap(hdcSource, width, height);
	HBITMAP hBitmapOld = (HBITMAP)SelectObject(hdcMemory, hBitmap);
	if (!BitBlt(hdcMemory, 0, 0, width, height, hdcSource, GxpSx, GypSy, CAPTUREBLT | SRCCOPY)) {
		cout << "BitBlt failed!" << endl;
		cout << GetLastError << endl;
	}

	//clean up
	DeleteObject(hBitmapOld);
	DeleteObject(hBitmap);
	ReleaseDC(NULL, hdcSource);

	return 0;
}


I am cleaning up my GDI objects as I go, but apparently not well enough. I did notice I've been using ReleaseDC as opposed to DeleteDC, but from what I've read that is correct since I'm using GetDC.

Would hdcMemory be the culprit? If so, how do I need to handle that once I've read the information?

How do I reduce or avoid stacking up so many GDI objects?
Last edited on
GetLastError is a function - so should be called as GetLastError().

You're displaying the address of the function!
Oof *face palm* not sure how I missed that... Well after fixing my mistake, it's an error code of 6 so "ERROR_INVALID_HANDLE".

I did for sure confirm I am hitting the ceiling of 10,000 GDI objects using the task manager. I need to nail down how to properly manage the objects being created. I'm not exactly sure what else I can do considering the code above is almost identical to syntax and use examples I've found online over the past two hours.

I guess my updated question is when / how can I delete the objects piling up?

My code is being used in this way:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

int get_Bitmap(int GxpSx, int GypSy, HDC& hdcMemory, int width, int height) { 
	HDC hdcSource = GetDC(NULL);													
	hdcMemory = CreateCompatibleDC(hdcSource);
	HBITMAP hBitmap = CreateCompatibleBitmap(hdcSource, width, height);
	HBITMAP hBitmapOld = (HBITMAP)SelectObject(hdcMemory, hBitmap);
	if (!BitBlt(hdcMemory, 0, 0, width, height, hdcSource, GxpSx, GypSy, CAPTUREBLT | SRCCOPY)) {
		cout << "BitBlt failed!" << endl;
		cout << GetLastError() << endl;
	}

	//clean up
	DeleteObject(hBitmapOld);
	DeleteObject(hBitmap);
	ReleaseDC(NULL, hdcSource);

	return 0;
}

void function_F(POINT GWindowO, POINT PS_Full, POINT status_bar, HDC& hcdMemory) {

	get_Bitmap(GWindowO.x, GWindowO.y, ref(hdcMemory), 432, 934);
	PS_status = GetPixel(hdcMemory, PS_Full.x, PS_Full.y);
	PS_status2 = GetPixel(hdcMemory, PS_Full.x - 100, PS_Full.y);
	caught_indc = GetPixel(hdcMemory, 216, 784);
	YS_Status = GetPixel(hdcMemory, status_bar.x, status_bar.y);

}



int main() { 

HDC hdcMemory = NULL;

function(GWindowO, PS_Full, status_bar, ref(hcdMemory));


}




But from what I can gather, I need to change my get_Bitmap function to something along the lines of this to dispose of hdcMemory:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
COLORREF get_Bitmap(int GxpSx, int GypSy, int width, int height, 
	COLORREF pixel_1, POINT pixel_1_coor) {
	HDC hdcSource = GetDC(NULL);													
	HDC hdcMemory = CreateCompatibleDC(hdcSource);
	HBITMAP hBitmap = CreateCompatibleBitmap(hdcSource, width, height);
	HBITMAP hBitmapOld = (HBITMAP)SelectObject(hdcMemory, hBitmap);
	if (!BitBlt(hdcMemory, 0, 0, width, height, hdcSource, GxpSx, GypSy, CAPTUREBLT | SRCCOPY)) {
		cout << "BitBlt failed!" << endl;
		cout << GetLastError() << endl;
	}

	pixel_1 = GetPixel(hdcMemory, pixel_1_coor.x, pixel_1_coor.y);


	//clean up
	DeleteObject(hBitmapOld);
	DeleteObject(hBitmap);
	ReleaseDC(NULL, hdcSource);
	DeleteDC(hdcMemory);

	return pixel_1;
}
Last edited on
Line 16: Instead of DeleteObject(hBitmapOld); you should SelectObject(hdcMemory, hBitmapOld);. See:

https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-selectobject

MSDN wrote:
This function returns the previously selected object of the specified type. An application should always replace a new object with the original, default object after it has finished drawing with the new object.


Also you may consider to create the dc/bitmap only once or when it changes. Particularly GetDC(...) is a time consuming operation. And you need to call ReleaseDC(...) after you are done with it. See:

https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdc
Topic archived. No new replies allowed.