Help with GDI drawing!

Started by
9 comments, last by flukus 20 years, 4 months ago
OK, I''m having a few problems getting GDI to work correctly. First of all I have this:

RECT fillrect;
fillrect.top = 0;
fillrect.left = 0;
fillrect.right = 640;
fillrect.bottom = 480;
//clear the backbuffer
FillRect(backbuffer, &fillrect, (HBRUSH)GetStockObject(WHITE_BRUSH));

 
Which basicly clears the bitmap that I have serving as the back buffer, but it only clears about 3/4 of the width of the bitmap, even if I set fillrect.right to 800+. Then theres this bit:

//get the client rectangle for blitting the back buffer
GetClientRect(hwnd, &clientRect);

//get the window DC
hdc = GetDC(hwnd);
//blitthe back buffer
BitBlt(hdc, clientRect.top, clientRect.left, clientRect.bottom, clientRect.right, backbuffer, 0, 0, SRCCOPY); 
//release the window dc
ReleaseDC(hwnd, hdc);

 
Which blits the back buffer to the window, this bit seems to be working correctly. But then when I try to draw to the back buffer: for (int i = 0; i <100; i++) { int x = rand()%640; int y = rand()%480; int r = rand()%255; int g = rand()%255; int b = rand()%255; SetPixel(backbuffer, x, y, RGB(r,g,b)); }//end for I get nothing. Sooo any ideas?
Advertisement
Here''s a link to my backbuffer thing with full screen GDI. You can use it to figure out where you went wrong. I got most of this from GameTutorials.com -- displays some polygon asteroids in full screen GDI with backbuffer. You have to set up your window correctly, and make sure it matches your ChangeDisplaySettings if you want full screen.

AsteroidsFullScreen.cpp | EXE

I''m about to "graduate" to DirectDraw though since I find GDI is too slow on slower machines (Pent II 300), but just fine with modern fast machines.

Phil P
Look up SetPixelV (think its the newest version)
at:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_25fa.asp

And of course, look over the obvious error-prone items such as, making sure you are seeding your rand calls correctly (and calling, not sure of the syntax)..flipping the back to the hdc, etc.

Pixel manipulation would be much faster tho (like lightning fast compared to setpixel), by converting the bitmap to a DIB then using [y*x+c]=RGB(.,.,.)..

I fseek, therefore I fam.

[edited by - drarem on November 18, 2003 2:54:41 AM]
I'll give you a beating like Rodney King who deserved it!=====================================Any and all ideas, theories, and text c2004,c2009 BrainDead Software. All Rights Reserved.
philVaz, I had a look through your code and I can''t see anything different to mine, but I''ll check again tommorow when I''ve had more sleep. Have fun with directx though, it''s so much nicer, no worrying about dc and selecting objects ect. DX won''t co-operate with my graphics card though unfortuneately.

Ok, I've looked through and compared the code thourougly and can't see anything wrong. I'll try posting the whole code:

console.cpp:

/////Tetris V2#define WIN32_LEAN_AND_MEAN//////////includes//////////////#include "mainheader.h"/////GLOBALS////////////////window handleHWND hwnd;//message for the event handlerMSG msg;//the window DCHDC hdc;//the dc for the backbufferHDC backbuffer = NULL;//the bitmap back bufferHBITMAP bb = NULL;//the old bitmap to return when the program endsHBITMAP hbmOld = NULL;//to hold the varios states of the game, mainly used in gamemain.cppconst int GAME_LOAD = 0;const int GAME_PLAY = 1;const int GAME_SHUTDOWN = 2;int GAME_STATE = GAME_LOAD;//////the event handlerLRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam){	//used in VM_PAINT	PAINTSTRUCT ps;		//process the message	switch (msg)	{	case WM_PAINT:		{			hdc = BeginPaint(hwnd, &ps);			EndPaint(hwnd, &ps);					return(0);		} break;	case WM_DESTROY:		{			//kill the app			PostQuitMessage(0);			return(0);		}break;	default: break;	}//end switch	//let windows deal with anything this didn't	return(DefWindowProc(hwnd, msg, wparam, lparam));}//end WindowProc//main functionint WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hprevinstance, LPSTR lpCmdLine, int ShowCmd){	//to hold the client rect of the window	RECT clientRect;		////////////CREATE THE WINDOW OBJECT	WNDCLASSEX winclass;	winclass.cbSize = sizeof(WNDCLASSEX);	winclass.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW;	winclass.lpfnWndProc = WindowProc;	winclass.cbClsExtra = 0;	winclass.cbWndExtra = 0;	winclass.hInstance = hinstance;	winclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);	winclass.hCursor = LoadCursor(NULL, IDC_ARROW);	winclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);	winclass.lpszMenuName = NULL;	winclass.lpszClassName = "winclass";	winclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);	//register the window	RegisterClassEx(&winclass);	//create the window	hwnd = CreateWindowEx(NULL, WINDOW_CLASS_NAME, NULL, WS_OVERLAPPED | WS_VISIBLE, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, NULL, NULL, hinstance, NULL);	//get the window DC	hdc = GetDC(hwnd);	//create a compatible dc	backbuffer = CreateCompatibleDC(hdc);	//CREATE A NEW BITMAP TO SERVE AS THE BACK BUFFER	bb = CreateCompatibleBitmap(backbuffer, SCREEN_WIDTH, SCREEN_HEIGHT);	//release the window bitmap	ReleaseDC(hwnd, hdc);	//select the bitmap into the DC	hbmOld = (HBITMAP)SelectObject(backbuffer, bb);			//initialize the game state	InitGameState();		////ENTER THE MAIN LOOP	while (true)	{		//see if thers a message and act		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))		{			//test for a quit			if (msg.message == WM_QUIT)				break;			//translate accelerator keys????			TranslateMessage(&msg);			//send the message to the event handler			DispatchMessage(&msg);		}//end if				RECT fillrect;		fillrect.top = 0;		fillrect.left = 0;		fillrect.right = 640;		fillrect.bottom = 480;		//clear the backbuffer		FillRect(backbuffer, &fillrect, (HBRUSH)GetStockObject(WHITE_BRUSH));		//call the game specific loop		GameMain();		//get the client rectangle for blitting the back buffer		GetClientRect(hwnd, &clientRect);		//get the window DC		hdc = GetDC(hwnd);		//blitthe back buffer		BitBlt(hdc, clientRect.top, clientRect.left, clientRect.bottom, clientRect.right, backbuffer, 0, 0, SRCCOPY); 		//release the window dc		ReleaseDC(hwnd, hdc);		//test for escape		if (KeyDown(VK_ESCAPE))			break;	}//end while	//SHUTDOWN GAME SPECIFIC STUFF	GameShutdown();	//restore the old bitmap to the dc	SelectObject(backbuffer, hbmOld);	//Delete the bitmap	DeleteObject(bb);	//delete the DC	DeleteDC(backbuffer);	//exit	return(msg.wParam);}//end WinMain 




gamemain.cpp:

#include "mainheader.h"RECT paddle = {320, 240, 380, 250};void GameMain(){	switch (GAME_STATE)	{	case 1: { GamePlay(); break;}	case 0: { GameLoad(); break;}	case 2: { GameShutdown(); break;}	default : {}	}//end switch}//end gameMain()void GamePlay(){	if (KeyDown(VK_LEFT))	{		paddle.left--;		paddle.right--;	}//end if	if (KeyDown(VK_RIGHT))	{		paddle.left++;		paddle.right++;	}//end if	for (int i = 0; i <100000; i++)	{		int x = rand()%640;		int y = rand()%480;		int r = rand()%255;		int g = rand()%255;		int b = rand()%255;				SetPixelV(backbuffer, x, y, RGB(r,g,b));	}//end for		//FillRect(backbuffer, &paddle, (HBRUSH)GetStockObject(WHITE_BRUSH));}//end game playvoid GameShutdown(){}//end game shutdownvoid GameLoad(){	srand(GetTickCount());}//end game loadvoid InitGameState(){	//this function is called befor the game loop is entered	GAME_STATE = 0;}//end init game state 


[edited by - flukus on November 18, 2003 11:48:25 PM]
In your WM_PAINT message, you are overwriting your hdc.

Do the hdc=GetDC(hwnd) in your WM_CREATE message of your WndProc().. get rid of the hdc=beginpaint() in your WM_PAINT and just use beginpaint/endpaint to paint your screen..
think of it as minimizing and maximizing, what GDI 'surfaces' do you need to restore (repaint)?

edit: after looking at it some more, you want to get rid of the other hdc=GetDC() call, and put your bitblt(hdc,...,backbuffer..) call into a render() function to make it easier.. that way you can call render() from WM_PAINT's BeginPaint/EndPaint. Then add a timer, so in pseudocode:

[PeekMessage]
translate()
getmessage()..
ELSE
WaitTime 0.005 uSeconds (or whatever interval you want)
mainloop();
ELSE
quit this game.
};

mainloop() {

if key=left arrow then do...
if key=right...

..
render(); //this is where bitblt could be to make it easy.
}

WndProc(....) {
case WM_CREATE:
hdc=GetDC(hwnd);
break;
case WM_PAINT:
BeginPaint(..,..);
render(); //this will call the bitblt function directly.
EndPaint..
..
};



I fseek, therefore I fam.

[edited by - drarem on November 18, 2003 12:34:42 AM]
I'll give you a beating like Rodney King who deserved it!=====================================Any and all ideas, theories, and text c2004,c2009 BrainDead Software. All Rights Reserved.
OK, I rearanged the code as you said but it still doesn''t want to work.

I solved the first problem of the fill rect not clearing the whole back buffer, I had clientRect.right/bottom switched.

The problem seems to be that I can''t do anything with the backbuffer from the gamemain.cpp file.
Doh! You can''t CreateCompatibleBitmap(backbuffer,..) because no bitmap object exists for it yet..

try:

CreateCompatibleBitmap(hdc,wid,hgt);

since you already (hopefully) did a hdc=GetDC(hwnd);
before it to move the value in the eax register returned from GetDC into variable hdc.

also, in your bitblt, your .left and .top are switched also,s/b:
bitblt(hdc,x,y,wdth,height,backdc,0,0,srccopy)



I fseek, therefore I fam.
I'll give you a beating like Rodney King who deserved it!=====================================Any and all ideas, theories, and text c2004,c2009 BrainDead Software. All Rights Reserved.
I tried putting the pixel drawing loop in render section and that works, sort of. The pixels show but there all in black and white. I tried making a using CreateBitmap instead of CreateCompatibleBitmap but when I do that the pixel plotting won''t work at all.
email me the source and I will see what I can do with it.. check my profile sig. for email addy.

You need to stick to CreateCompatibleBitmap(hdc...)

CreateCompatibleBitmap(backbuffer...) won't work, backbuffer is a non-existant object at this point.


Yes, you need to use:

backbuffer=CreateCompatibleDC(hdc)..
backBMP = CreateCompatibleBitmap(hdc,...,...);
SelectObject(backbuffer,backBMP);

but backbuffer doesn't have a bitmap associated with it (via SelectObject), so it aint gonna work.

I fseek, therefore I fam.

[edited by - drarem on November 19, 2003 4:54:40 AM]
I'll give you a beating like Rodney King who deserved it!=====================================Any and all ideas, theories, and text c2004,c2009 BrainDead Software. All Rights Reserved.

This topic is closed to new replies.

Advertisement