Sign in to follow this  
RamboBiafra

strange bug

Recommended Posts

hello everyone! I have developed a game in c++ using only win32 API (no dx at all). Game runs fine but after an hour or so, it draws a single frame on desktop that stays there no matter what i do. Game keeps working fine after that and there are no other problems whatsoever, except the fact that strange frame stays on desktop covering icons. This happens mainly when i switch between different windows during the gameplay but also when i run game in full screen mode. The strange thing is that it happens after so much time (an hour) and that game still works fine after that. I have excluded possibilities of memory leaks or wrong window handles. If anyone had this kind of problem or knows what caused it please let me know.

Share this post


Link to post
Share on other sites
I haven't solved this problem yet. It seems that application somehow, somewhere gets a wrong DC (the screen DC) and starts rendering on top of all other windows. The game window still recieves the input but animation and all graphics are rendered outside window. I cant think of any other thing that could cause this except using wrong DC.
I belive there is no way my code could mess up DCs, but here is some code i use:


// BACKBUFFER CLASS
//==================

class BackBuffer {
private:

HWND mhWnd; // Window handle
HDC mhDC; // DC handle
HBITMAP mhSurface; // Surface bitmap
HBITMAP mhOldObject; // Previous bitmap
int mWidth; // Bitmap width
int mHeight; // Bitmap height

.....

public:

// CONSTRUCTOR
//============
BackBuffer( HWND hWnd, int width, int height ) {
mhWnd = hWnd;
mWidth = width;
mHeight = height;

HDC hWndDC = GetDC( hWnd );
mhDC = CreateCompatibleDC( hWndDC );

mhSurface = CreateCompatibleBitmap( hWndDC, width, height );
ReleaseDC( hWnd, hWndDC );

mhOldObject = (HBITMAP)SelectObject( mhDC, mhSurface );

HBRUSH White = (HBRUSH)GetStockObject( LTGRAY_BRUSH );
HBRUSH OldBrush = (HBRUSH)SelectObject( mhDC, White );

Rectangle( mhDC, 0, 0, mWidth, mHeight );

SelectObject( mhDC, OldBrush );
};

// PRESENT BUFFER
//===============
void Present() {
HDC hWndDC = GetDC( mhWnd );
BitBlt( hWndDC, 0, 0, mWidth, mHeight, mhDC, 0, 0, SRCCOPY );
ReleaseDC( mhWnd, hWndDC );
};

// GET DC FUNCTION
//=============
HDC GetHDC() { return mhDC; };

......
// SOME OTHER FUNCTIONS
......
};

// SPRITE CLASS
//=============

class Sprite {
private:

HINSTANCE mhAppInstance; // Application handle
HBITMAP mhImage; // Bitmap image handle
HBITMAP mhMask; // Bitmap mask handle
BITMAP mImageBM; // Bitmap image
BITMAP mMaskBM; // Bitmap mask
RECT mBitmapRect; // Bitmap rectangle
POINT mCenterPosition; // Bitmap center
int ImageID; // Bitmap image ID

public:

// CONSTRUCTOR
//============
Sprite( HINSTANCE hAppInstance, int imageID, int maskID, POINT pos ) {
mhAppInstance = hAppInstance;
ImageID = imageID;
mCenterPosition.x = pos.x;
mCenterPosition.y = pos.y;

mhImage = LoadBitmap( hAppInstance, MAKEINTRESOURCE(imageID) );
mhMask = LoadBitmap( hAppInstance, MAKEINTRESOURCE(maskID) );

GetObject( mhImage, sizeof(BITMAP), &mImageBM );
GetObject( mhMask, sizeof(BITMAP), &mMaskBM );

assert(mImageBM.bmWidth == mMaskBM.bmWidth);
assert(mImageBM.bmHeight == mMaskBM.bmHeight);

mBitmapRect.right = mCenterPosition.x + GetWidth()/2;
mBitmapRect.bottom = mCenterPosition.y + GetHeight()/2;

mBitmapRect.left = mCenterPosition.x - GetWidth()/2;
mBitmapRect.top = mCenterPosition.y - GetHeight()/2;
};

// SOME OTHER FUNCTIONS
......

// DRAW SPRITE FUNCTION
//=====================
virtual void Draw( HDC hBackBufferDC, HDC hSpriteDC ) {
int w = GetWidth();
int h = GetHeight();

int x = mCenterPosition.x - (w/2);
int y = mCenterPosition.y - (h/2);

HGDIOBJ oldObj = SelectObject(hSpriteDC, mhMask);

BitBlt(hBackBufferDC, mBitmapRect.left, mBitmapRect.top, mBitmapRect.right,
mBitmapRect.bottom, hSpriteDC, 0, 0, SRCAND);

SelectObject(hSpriteDC, mhImage);

BitBlt(hBackBufferDC, mBitmapRect.left, mBitmapRect.top, mBitmapRect.right,
mBitmapRect.bottom, hSpriteDC, 0, 0, SRCPAINT);

SelectObject(hSpriteDC, oldObj);
};

};

// GAME CLASS
//===========

class Game {
private:

HWND hMainWnd; // Window handle
BackBuffer* pBackBuffer; // Pointer to backbuffer
HDC hSpriteDC; // Sprite dc
Sprite* Background; // example sprite

.....

// DRAW FRAME FUNCTION
//====================
void DrawFrame( double deltaTime ) {
HDC dc = pBackBuffer->GetHDC();
// draw sprites using dc like:
Background->Draw( dc, hSpriteDC );
.....
};

public:
.....

// INITIALIZE GAME FUNCTION
//=========================
int GCInitialize( HINSTANCE hInstance ) {
.....
// SOME OTHER STUFF
.....
hSpriteDC = CreateCompatibleDC(0);
pBackBuffer = new BackBuffer( hMainWnd, Width, Height );
};

// GAME (MESSAGE) LOOP
//====================
int GameLoop() {
MSG Message;
ZeroMemory( &Message, sizeof(MSG) );

// CALCULATE TIME PASSED
......

while( Message.message != WM_QUIT )
{
if( PeekMessage( &Message, 0, 0, 0, PM_REMOVE ) )
{
TranslateMessage( &Message );
DispatchMessage( &Message );
}
else
{
if( timeElapsed >= 0.07 )
{
DrawFrame( deltaTime );
pBackBuffer->Present();
timeElapsed = 0.0;
}
lastTime = currTime;
}
}
.....
};

};




I think there is no way this code could render on desktop but something wrong happens after an hour of play. I forgot to say that after 5 minutes or so, it gets back to normal again (it starts rendering correctly - no more desktop frames).

Here is the screenshot of bug: screenshot

if anyone has any idea what can be wrong, please tell me.

Share this post


Link to post
Share on other sites

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