Sign in to follow this  

Double Buffering problem about Win32

This topic is 4865 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

i explained the problem at the beginning of the code.Although the code is a little long .You will look just 3 function in it to correct the matter. anyway here is the code.. thanks for your replys
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <windowsx.h>
#include "resource.h"
#include <stdlib.h>
#include <time.h>

/* 
     My aim is create a double buffering.All Creatures will paint them to ImageDC by their
	 CAnyObject::Show() funciton and then SDBuffer::Show() function will first Paint ImageDC
	 to the MemoryDC(DoubleBuffering Dc) and Then Paint them to the WindowHdc(Window's orginal
	 Hdc) we need MemoryDC because before copying every ImageDC content to memoryDc we will 
	 fill MemoryDC with BackgroundBitmap...
	 By just examining ProgramMain() CAnyObject::Show()  SDBuffer()::Show() and the part before
	 the WinMain's while(true) PeekMessage(..) part (initializing of SDBuffer and WindowHdc)
	 you can correct the problem
	 Ý could'Nt understand why this is not working 
	 ýmage1 ÝS 100*100  BÝTMAP 
	 image2 is 1024* 768 background bitmap 
	 thanks for your replys
*/


//////////////////////////////////////////GLOBAL & CONSTANTS//////////////////////////////////
const char* const MYCLASSTYPE="Serdar'ýn Sýnýfý";
const char* const WINDOWCAPTION="******** Sorunsuz Gezen Dragon *******";
const int SCREENXLENGTH=1024;
const int SCREENYLENGTH=768;
HINSTANCE SpareHInstance=NULL; //Null for now
HBITMAP BackgroundBitmap=NULL;//Null for now
HDC ImageDC=NULL;             //Null for now
enum GAMESTATE { GAMEINITIALIZE,GAMESTART,GAMERUN,GAMEEXIT,GAMESTOP};
GAMESTATE StateOfGame=GAMEINITIALIZE;

///////////////////////////////GLOBAL FUNC. CLASSES & STRUCTURES///////////////////////////////
bool LockFrameRate(int FrameRate=33)
{
	static float LastTime=0.0F;
	float CurrentTime=(float)GetTickCount();  //1 second ==1000 milisecond
	if( CurrentTime-LastTime >= (1000.0F/FrameRate) )
	{
		LastTime=CurrentTime;
		return true;
	}
	return false;
}
int ProgramMain(HWND& hwnd,HDC& hdc);
struct SDBuffer
{
	HWND WindowHwnd;
	HDC WindowHdc;
	HDC MemoryHdc;
	RECT ClientRect;
	HBITMAP BackBufferBitmap;
	HBITMAP OldBitmap;
	SDBuffer():WindowHwnd(NULL),WindowHdc(NULL),MemoryHdc(NULL),BackBufferBitmap(NULL) {};
	bool Initialize();
	bool Free();
	bool Show();
	virtual ~SDBuffer();
};;
bool SDBuffer::Initialize()
{
	if(WindowHwnd==NULL)
	{
		return false;
	}
	MemoryHdc=CreateCompatibleDC(WindowHdc);
	if(!MemoryHdc)
	{
		return false;
	}
	GetClientRect(WindowHwnd,&ClientRect);
	BackBufferBitmap=CreateCompatibleBitmap(WindowHdc,ClientRect.right,ClientRect.bottom);
	OldBitmap=(HBITMAP)SelectObject(MemoryHdc,BackBufferBitmap);
	return true;
}
bool SDBuffer::Free()
{
	SelectObject(MemoryHdc,OldBitmap);
	DeleteDC(MemoryHdc);
	DeleteObject(BackBufferBitmap);
	return true;
}
SDBuffer::~SDBuffer()
{
	Free();
}
bool SDBuffer::Show()
{
	HBRUSH BackgroundAsBrush=CreatePatternBrush(BackgroundBitmap);
	FillRect(MemoryHdc,&ClientRect,BackgroundAsBrush);
	BitBlt(MemoryHdc,0,0,SCREENXLENGTH,SCREENYLENGTH,ImageDC,0,0,SRCCOPY);
	BitBlt(WindowHdc,0,0,SCREENXLENGTH,SCREENYLENGTH,MemoryHdc,0,0,SRCCOPY);
	DeleteObject(BackgroundAsBrush);
	return true;
}
SDBuffer MyBufferingStruct;  //Double Buffering structure
class CAnyObject
{
protected:
	int Xco,Yco;
	HBITMAP Image;
	int VelocityX,VelocityY;
public:
	CAnyObject():Xco(rand()%SCREENXLENGTH),Yco(rand()%SCREENYLENGTH),VelocityX(rand()%20),
		VelocityY(rand()%20)
	{
		Image=(HBITMAP)LoadImage(SpareHInstance,MAKEINTRESOURCE(IDB_BITMAP1),IMAGE_BITMAP
			                     ,0,0,NULL);
	}
	void Show(HDC& ImageHdc)const;
	void Free();
	virtual ~CAnyObject();
	void Move();
};
void CAnyObject::Show(HDC& ImageHdc) const
{
	HDC TempMemoryDC=CreateCompatibleDC(MyBufferingStruct.WindowHdc);
	HBITMAP OldBitmap=(HBITMAP)SelectObject(TempMemoryDC,Image);
	COLORREF TransparentColor=RGB(255,255,255);
	TransparentBlt(ImageHdc,Xco,Yco,100,100,TempMemoryDC,0,0,SCREENXLENGTH,SCREENYLENGTH
		           ,TransparentColor);
	SelectObject(TempMemoryDC,OldBitmap);
	DeleteDC(TempMemoryDC);
	DeleteObject(OldBitmap);
}
void CAnyObject::Free()
{
	if(!Image)
	{
		DeleteObject(Image);
	}
}
CAnyObject::~CAnyObject()
{
	Free();
}
void CAnyObject::Move()
{
	Xco+=VelocityX;
	Yco+=VelocityY;
	if(Xco+100>SCREENXLENGTH)  //Image is 100*100...
	{
		VelocityX*=-1;
	}
	if(Yco+100>SCREENYLENGTH)
	{
		VelocityY*=-1;
	}
	if(Xco<0) { VelocityX*=-1; }
	if(Yco<0) { VelocityY*=-1; }
	VelocityX=(rand()%30)?VelocityX:rand()%20;
	VelocityY=(rand()%30)?VelocityY:rand()%20;
}


///////////////////////////////////////WINPROC//////////////////////////////////////////////
LRESULT CALLBACK WinProc(HWND hwnd,UINT msg,WPARAM wparam,LPARAM lparam)
{
	PAINTSTRUCT ps;
	HDC WinProcHdc;
	switch(msg)
	{
	case WM_CREATE:
		{
			return 0;
		}
		break;
	case WM_PAINT:
		{
			WinProcHdc=BeginPaint(hwnd,&ps);
			EndPaint(hwnd,&ps);
			ReleaseDC(hwnd,WinProcHdc);
			return 0;
		}
		break;
	case WM_KEYDOWN:
		{
			switch(wparam) //contains virtual ScanCodes
			{
			case VK_ESCAPE:
				{
					PostQuitMessage(0);
				}
				break;
			}
			return 0;
		}
		break;
	case WM_DESTROY:
		{
			PostQuitMessage(0);
			return 0;
		}
		break;
	}
	return DefWindowProc(hwnd,msg,wparam,lparam);
}

////////////////////////////////////////WINMAIN////////////////////////////////////////////////
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
{
	WNDCLASSEX MyClass;
	HWND hwnd;
	MSG msg;
	MyClass.cbClsExtra=0;
	MyClass.cbSize=sizeof(WNDCLASSEX);
	MyClass.cbWndExtra=0;
	MyClass.hbrBackground=NULL;
	MyClass.hCursor=LoadCursor(NULL,IDC_ARROW);
	MyClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
	MyClass.hIconSm=LoadIcon(NULL,IDI_APPLICATION);
	MyClass.hInstance=hInstance;
	MyClass.lpfnWndProc=WinProc;
	MyClass.lpszClassName=MYCLASSTYPE;
	MyClass.lpszMenuName=NULL;
	MyClass.style=CS_HREDRAW|CS_VREDRAW|CS_OWNDC|CS_DBLCLKS;
	if(!(RegisterClassEx(&MyClass)))
	{
		return 0;
	}
	if(!(hwnd=CreateWindowEx(NULL,MYCLASSTYPE,WINDOWCAPTION,WS_POPUP,CW_USEDEFAULT,CW_USEDEFAULT,
		                     CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,hInstance,NULL)))
	{
		return 0;
	}
	UpdateWindow(hwnd);
	ShowWindow(hwnd,SW_SHOWMAXIMIZED);
	BackgroundBitmap=(HBITMAP)LoadImage(hInstance,MAKEINTRESOURCE(IDB_BITMAP2),
		              IMAGE_BITMAP,0,0,NULL);
	SpareHInstance=hInstance;
	HDC WindowHdc=GetDC(hwnd);
	ImageDC=CreateCompatibleDC(WindowHdc);
	HBITMAP OldBitmap=(HBITMAP)SelectObject(ImageDC,BackgroundBitmap);
	MyBufferingStruct.WindowHdc=WindowHdc;
	MyBufferingStruct.WindowHwnd=hwnd;
	MyBufferingStruct.Initialize();
	while(true)
	{
		if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
		{
			if(msg.message==WM_QUIT)
			{
				break;
			}
		    TranslateMessage(&msg);
		    DispatchMessage(&msg);
		}
		if(LockFrameRate())
		{
			ProgramMain(hwnd,ImageDC);
		}
	}
	ReleaseDC(hwnd,WindowHdc);
	DeleteDC(ImageDC);
	DeleteObject(BackgroundBitmap);
	UnregisterClass(MYCLASSTYPE,hInstance);
	DeleteObject(OldBitmap);
	return msg.wParam;
}

////////////////////////////////////////PROGRAMMAIN////////////////////////////////////////////
int ProgramMain(HWND& hwdn,HDC& hdc)
{
	static CAnyObject MyObject;
	switch(StateOfGame)
	{
	case GAMEINITIALIZE:
		
		StateOfGame=GAMESTART;
		return 1;
		break;
	case GAMESTART:
		{
			//insert some code here..
			StateOfGame=GAMERUN;
			return 1;
		}
		break;
	case GAMERUN:
		{
			MyObject.Move();
			MyObject.Show(hdc);
			MyBufferingStruct.Show();
			return 1;
		}
		break;
	}
	return 1;
}

Share this post


Link to post
Share on other sites
You explained what you want to happen, but you never explained what actually is happening that is contrary to what you want. Without that information, finding the cause is going to be a lot more difficult, since we'd also need to find the problem. So [cliche]help us out a bit more so that we might be able to better help you[/cliche].

Share this post


Link to post
Share on other sites
aaa all i want is to see my 100*100 bitmap is moving at the screen without flickering
but nothing is moving on screen
mybitmap (CAnyObject::Image is loaded from resource script)
and Background bitmap is loadded from bitmap too..
The problem is i only see backgroundbitmap but MyCAnyOjbect's ýmage is invisible i cant see it..
There must be something i am doing wrong in these
CAnyObject::Show() -> Maybe this one can't bitblt its image to
the ImageDC
SDBuffer::Show() ->Maybe that one can't bitblt its memoryHdc(BackbufferHdc) to the WindowHdc

or MyDouble buffering logic has some errors

Share this post


Link to post
Share on other sites
Me too,I did not exactly understand the prob.

When you create a backbuffer in Win32 gdi,you will get an HDC to the backbuffer,and using this HDC you can call all the funtions which you use on the screen's hdc to draw text,pixels,bitmaps etc. to the backbuffer

And after you have done drawing,just copy the backbuffer to the screen.

Comes anywhere near the prob?...

//Edit:
First draw your background to the backbuffer,then draw the image to the backbuffer and blit the backbuffer to the screen.There should be no problems doing that I think.

Share this post


Link to post
Share on other sites

This topic is 4865 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this