Device Context has a memory???

Started by
8 comments, last by angry 18 years, 8 months ago
I'm drawing on a window I created with text using the textout function. Basically if one event occurs, then one thing is written to the screen (via textout) and if another occurs then another text should be output. The thing is, I would think that once I called DeleteDC to delete the temp DC and EndPaint, that any memory of what was written would be erased. Thr problem is, when one event is over and I write to the screen the next event occuring, it still shows event 1. below is a code snippet....

case WM_PAINT:

/* display the main window first --------------------------*/
	hdc  = BeginPaint(hWnd, &ps);
	hdc2 = CreateCompatibleDC(hdc);
	SelectObject(hdc2, MainWindow_SCREEN);
	SetBkColor(hdc2, RGB(167,167,167));

	switch (event_mode){

	  case EVENT1: // display event 1

		TextOut(hdc2, 295, 100, "EVENT1", 6);

		break;

	  case EVENT2: // display event 2

		TextOut(hdc2, 344, 30, "EVENT2", 6);

		break;

	} // end switch

	// now blt everything from the back buffer hdc2 to the main display hdc
	BitBlt(hdc, 0, 0, 806, 632, hdc2, 0, 0, SRCCOPY);

	/* Cleanup DC's and any other stuff---------------------*/
	EndPaint(hWnd, &ps);
	DeleteDC(hdc);
	DeleteDC(hdc2);

	return 0;


basically the screen should print "event 1" then when event2 occurs it should print "event 2" each event is exclusive, meaning only one printing should occur. The problem is that when event2 is printed, event1 is still showing on the screen, i thought by just eliminating it from the printing of event2, that event 1 would not be printed, but it still is.... any ideas??? Thx!! [Edited by - Andrew Russell on July 27, 2005 9:23:56 AM]
~Bolt"All men dream: but not equally. Those who dream by night in the dusty recesses of their minds wake in the day to find that it was vanity: but the dreamers of the day are dangerous men, for they may act their dreams with open eyes, to make it possible." This I did...
Advertisement
Dude, you gotta fix your post.
The BeginPaint exludes areas that's not in the update region, to update the whole dc you could use the InvalidateRgn or something similiar.
I don't understand why you use the CreateCompatibleDC each time the WM_PAINT message are called, you already have your dc:)
You're making this call:
SelectObject(hdc2, MainWindow_SCREEN);

I'm not really sure of what the MainWindow_SCREEN represents, but I guess it is a bitmap, however you never unselect it from the dc before you delete the dc. Which I think you must do...


Also I can't see that you're clearing the bitmap in the backbuffer dc.
I called createcompatibleDC(hdc) because further down I deleted the DC.
~Bolt"All men dream: but not equally. Those who dream by night in the dusty recesses of their minds wake in the day to find that it was vanity: but the dreamers of the day are dangerous men, for they may act their dreams with open eyes, to make it possible." This I did...
I don't see where your copy the stuff of your temp dc into you regular one?

LRESULT CALLBACK WindowProc(HWND hwnd,message                            UINT uMsg,                            WPARAM wParam,                            LPARAM lParam){  switch(uMsg)  {    case WM_CLOSE:	  PostQuitMessage(0);          return 0;	  break;	case WM_KEYDOWN:		{			if(wParam == VK_LEFT)                        {				g_Event = 1;                                InvalidateRgn(hwnd,NULL,TRUE);                        }			else			if(wParam == VK_RIGHT)                        {				g_Event = 2;                                InvalidateRgn(hwnd,NULL,TRUE);                        }						return 0;		} break;	case WM_PAINT:		{			PAINTSTRUCT ps;			HDC hdc = BeginPaint(hwnd,&ps);			if(g_Event == 1)			{				TextOut(hdc,10,10,"EVENT ONE",9);			} else			if(g_Event == 2)			{				TextOut(hdc,10,10,"EVENT TWO",9);			}			EndPaint(hwnd,&ps);			return 0;		} break;	default:	  break;  }  return DefWindowProc(hwnd,uMsg,wParam,lParam);}
I got it to finally work, here's what I did that was different:

1.) I created to "helper" hdc's from createcompatibledc, and then I loaded them with bitmaps, using createcompatiblebitmap.

2.) I then loaded the "helper" hdc's with the bitmaps i needed and then blitted them to the main hdc (hdc2)

3.) I then textout to hdc2

4.) I then bitblt from hdc2 to hdc

/* display the main window first --------------------------*/hdc  = BeginPaint(hWnd, &ps);hdc2 = CreateCompatibleDC(hdc);hdc3 = CreateCompatibleDC(hdc);SelectObject(hdc2, CreateCompatibleBitmap(hdc, 800, 600));SelectObject(hdc3, CreateCompatibleBitmap(hdc, 800, 600));SelectObject(hdc3, MainWindow_HANDLE);BitBlt(hdc2, 0, 0, 800, 600, hdc3, 0, 0, SRCCOPY);    switch (display_mode){	case EVENT1:	    // display event1	    TextOut(hdc2, 295, 100, "EVENT1", 6);	    break;	case EVENT2:	    TextOut(hdc2, 344, 30, "EVENT2", 6);	    break;    }// end switch    // now blt everything from the back buffer hdc2 to the main display hdc    BitBlt(hdc, 0, 0, 800, 600, hdc2, 0, 0, SRCCOPY);    /* Cleanup DC's and any other stuff---------------------*/    EndPaint(hWnd, &ps);    DeleteDC(hdc2);    DeleteDC(hdc3);    return 0;
~Bolt"All men dream: but not equally. Those who dream by night in the dusty recesses of their minds wake in the day to find that it was vanity: but the dreamers of the day are dangerous men, for they may act their dreams with open eyes, to make it possible." This I did...
A tip is not to recreate your buffer surface every time you receive a WM_PAINT message.

HWND g_hwnd = NULL;HDC g_hDC = NULL;HDC g_hOffscreen = NULL;int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,nCmdLine){  ...   ...  ...  g_hDC = GetDC(g_hwnd);  // Create a buffer  g_hOffscreen = CreateCompatibleDC(g_hDC);    HBITMAP hbmp = CreateCompatibleBitmap(g_hOffscreen,SCREEN_WIDTH,SCREEN_HEIGHT);  SelectObject(g_hOffscreen,hbmp);  DeleteObject(hbmp);  ...  ...  ...  if(g_hOffscreen)  {    DeleteDC(g_hOffscreen);    g_hOffscreen = NULL;  }}

Quote:Original post by Boltimus
I got it to finally work, here's what I did that was different:

1.) I created to "helper" hdc's from createcompatibledc, and then I loaded them with bitmaps, using createcompatiblebitmap.

2.) I then loaded the "helper" hdc's with the bitmaps i needed and then blitted them to the main hdc (hdc2)

3.) I then textout to hdc2

4.) I then bitblt from hdc2 to hdc

*** Source Snippet Removed ***
That's no good. Now you have a couple of resource leaks (via CreateCompatibleBitmap).
I'd excpect your program to run out of memory or resources pretty fast and crash with it like that. [sick]

You also must listen to 'angry's advice and unselect the things you select into the dc.
This means that you need to store the results of CreateCompatibleBitmap and SelectObject into variables so that you can cleanup and restore stuff after the drawing.

I'm also quite sure that you don't need to create two large bitmaps for every WM_PAINT message!!!
"In order to understand recursion, you must first understand recursion."
My website dedicated to sorting algorithms
Hmmm... I think you want something like this:
//... in WM_PAINTHDC hdcBack = CreateCompatibleDC(hdc);HBITMAP hbmBack = CreateCompatibleBitmap(hdc, 800, 600);HBITMAP hbmPrev = (HBITMAP)SelectObject(hdcBack, hbmBack);TextOut(hdcBack, 100, 100, "Hello World!", 12);BitBlt(hdc, 0, 0, 800, 600, hdcBack, 0, 0, SRCCOPY);// unselect the backbuffer bitmap from the backbuffer dc // otherwise you can't delete it.SelectObject(hdcBack, hbmPrev);DeleteObject(hbmBack);// delete the backbuffer dcDeleteDC(hdcBack);


Also I can see that you're deleting the device context which is returned by the BeginPaint() function, and this is something I think you should not do. I think EndPaint() does this for you. Remember the BeginPaint() returns a device context of a window. And a device context retrieved from a window must be released with ReleaseDC(), however as I said earlier, I think EndPaint() does this for you.

And what does this do?
SelectObject(hdc3, MainWindow_HANDLE);
What type is MainWindow_HANDLE? And what is it?

This topic is closed to new replies.

Advertisement