• Advertisement
Sign in to follow this  

DirectX in a Window(need help)

This topic is 4551 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

So my program starts but it looks like weird random Graphic Errors O.o im linking to ddraw.lib dxguid.lib FreeImage.lib my files are: -bouncy_main.cpp -bouncy_classes.h -bouncy_functions.h -bouncy_resource.h -bouncy_resource.rc bouncy_main.cpp:
#include <windows.h>
#include <FreeImage.h>
#include <ddraw.h>
#include "bouncy_resource.h"
#include "bouncy_functions.h"
#include "bouncy_classes.h"

BitMapObject bmoBall;
BitMapObject bmoBackground;
HBITMAP hBall;
HWND hWnd;
CBouncyBall BallClass;

LPDIRECTDRAW7 lpDD;
LPDIRECTDRAWSURFACE7 lpDDSPrimary;
LPDIRECTDRAWSURFACE7 lpDDSBack;
LPDIRECTDRAWCLIPPER  lpDDClipper;

int Bouncy_Points;
bool done;
bool bRunGame;

LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){
	switch(message){
		case WM_SIZE:
		{
			SetWindowPos(hWnd,0,0,0,400,500,SWP_NOMOVE | SWP_NOZORDER);
			return(0);
		}break;
		case WM_COMMAND:
		{
			switch(LOWORD(wParam)){
				case MENUID_CLOSE:
				{
                    PostMessage(hWnd,WM_DESTROY,0,0);
					return(0);
				}break;
			}
		}break;
		case WM_KEYDOWN:
		{
		switch(wParam){
			case VK_ESCAPE:
			{
				PostMessage(hWnd,WM_DESTROY,0,0);
				return(0);
			}break;
		}
		}break;
		case WM_DESTROY:
		{
			done=true;
			return(0);
		}break;
		case WM_ACTIVATE:
		{
			if( LOWORD( wParam ) == WA_INACTIVE )
{
    
    bRunGame = false;
}
else
{
    
    bRunGame = true;
}
		}break;
		default:break;
	}
	return(DefWindowProc(hWnd,message,wParam,lParam));
}
int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow){
	MSG message;
	WNDCLASSEX bouncyMain;
	bouncyMain.cbSize=sizeof(WNDCLASSEX);
	bouncyMain.style=CS_HREDRAW|CS_VREDRAW;
	bouncyMain.lpfnWndProc=WindowProc;
	bouncyMain.cbClsExtra=0;
	bouncyMain.cbWndExtra=0;
	bouncyMain.hInstance=hinst;
	bouncyMain.hIcon=LoadIcon(NULL,IDI_WINLOGO);
	bouncyMain.hCursor=LoadCursor(NULL,IDC_ARROW);
	bouncyMain.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);
	bouncyMain.lpszMenuName=MAKEINTRESOURCE(MAIN_MENU);
	bouncyMain.lpszClassName="BouncyMainClass";
	bouncyMain.hIconSm=LoadIcon(NULL,IDI_WINLOGO);
	if(!RegisterClassEx(&bouncyMain))return(0);
	if(!(hWnd=CreateWindowEx(NULL,
                             "BouncyMainClass",
                             "Bouncy Ball",
                             WS_BORDER | WS_SYSMENU | WS_VISIBLE,
                             200, 200,
                             400, 500,
                             NULL,
                             NULL,
                             hinst,
                             NULL)))return(0);
    ShowWindow(hWnd,SW_SHOWNORMAL);
    UpdateWindow(hWnd);
    if(!Bouncy_Init())return(0);
    FreeImage_Initialise(false);
    done=false;
    while(!done){
    	while(PeekMessage(&message,hWnd,0,0,PM_REMOVE)){
    		TranslateMessage(&message);
    		DispatchMessage(&message);
    	}
    	GameLoop();
    }
    Bouncy_EndDDraw();
    PostQuitMessage(0);
	return(0);
}
bool Bouncy_Init(void){
    if(!Bouncy_InitDDraw())return(false);
    return(true);
}
bool Bouncy_InitDDraw(void){
	HRESULT ddrval;
	ddrval=DirectDrawCreateEx(NULL,(LPVOID *)&lpDD,IID_IDirectDraw7,NULL);
	if(ddrval!=DD_OK){
		return(false);
	}
	ddrval=lpDD->SetCooperativeLevel(hWnd,DDSCL_NORMAL);
	if(ddrval!=DD_OK){
		lpDD->Release();
		return(false);
	}
	DDSURFACEDESC2 ddsd;
	ZeroMemory(&ddsd,sizeof(ddsd));
	ddsd.dwSize=sizeof(ddsd);
	ddsd.dwFlags=DDSD_CAPS;
	ddsd.ddsCaps.dwCaps=DDSCAPS_PRIMARYSURFACE;
	ddrval=lpDD->CreateSurface(&ddsd,&lpDDSPrimary,NULL);
	if(ddrval!=DD_OK){
		lpDD->Release();
		return(false);
	}
ZeroMemory(&ddsd, sizeof(ddsd));

ddsd.dwSize = sizeof( ddsd );
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
ddsd.dwWidth = 400; 
ddsd.dwHeight = 500; 
ddrval=lpDD->CreateSurface(&ddsd,&lpDDSBack,NULL);
if(ddrval!=DD_OK){
	lpDD->Release();
	lpDDSPrimary->Release();
	return(false);
}
ddrval=lpDD->CreateClipper(0,&lpDDClipper,NULL);
if(ddrval!=DD_OK){
	lpDD->Release();
	lpDDSPrimary->Release();
	lpDDSBack->Release();
	return(false);
}
ddrval=lpDDClipper->SetHWnd(0,hWnd);
if(ddrval!=DD_OK){
	lpDDClipper->Release();
	lpDDSPrimary->Release();
	lpDDSBack->Release();
	lpDD->Release();
	return(false);
}
ddrval=lpDDSPrimary->SetClipper(lpDDClipper);
if(ddrval!=DD_OK){
		lpDDClipper->Release();
	lpDDSPrimary->Release();
	lpDDSBack->Release();
	lpDD->Release();
	return(false);
}
	return(true);
}
bool Bouncy_EndDDraw(void){
	if(lpDDSBack){
		lpDDSBack->Release();
		lpDDSBack=NULL;
	}
	if(lpDDSPrimary){
		lpDDSPrimary->SetClipper(NULL);
		lpDDClipper=NULL;
		lpDDSPrimary->Release();
		lpDDSPrimary=NULL;
	}
	if(lpDD){
		lpDD->Release();
		lpDD=NULL;
	}
	return(true);
}
bool GameLoop(){
    if(bRunGame){
    	DrawAll();
    }
	return(true);
}
bool DrawAll(){
    DDSURFACEDESC2 ddsd;
    UCHAR *VRam;
    int Linewidth;
    int x,y;
    ZeroMemory(&ddsd,sizeof(ddsd));
    ddsd.dwSize=sizeof(ddsd);
    lpDDSBack->Lock(NULL,&ddsd,DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT,NULL);
    Linewidth=ddsd.lPitch;
    VRam=(UCHAR *)ddsd.lpSurface;
    for(y=0;y<200;y++){
    for(x=0;x<200;x++){
    	VRam[x+y*Linewidth]=245;
    }
    }
    lpDDSBack->Unlock(NULL);
    Bouncy_Flip();
	return(true);
}
bool Bouncy_Flip(void){
	RECT rect;
	ZeroMemory(&rect,sizeof(rect));
	GetClientRect(hWnd,&rect);
	POINT p1;
	POINT p2;
	p1.x=rect.left;
	p1.y=rect.top;
	p2.x=rect.right;
	p2.y=rect.bottom;
	ClientToScreen(hWnd,&p1);
	ClientToScreen(hWnd,&p2);
	rect.left=p1.x;
	rect.top=p1.y;
	rect.right=p2.x;
	rect.bottom=p2.y;
	lpDDSPrimary->Blt(&rect,lpDDSBack,NULL,DDBLT_WAIT,NULL);
	return(true);
}

bouncy_functions.h:
bool Bouncy_Init(void);
bool GameLoop();
bool DrawAll();
bool Bouncy_InitDDraw(void);
bool Bouncy_EndDDraw(void);
bool Bouncy_Flip(void);


bouncy_classes.h:
#include <windows.h>
class BitMapObject
{
	private:
	  HDC hdcMemory;
	  HBITMAP hbmNewBitMap;
	  HBITMAP hbmOldBitMap;
	  int iWidth, iHeight;
    public:
      BitMapObject();
      ~BitMapObject();
      void Load(HDC hdcCompatible, HBITMAP hLoad);
      void Create(HDC hdcCompatible, int width, int height);
      void Destroy();
      int GetWidth();
      int GetHeight();
      operator HDC();
};

BitMapObject::BitMapObject()
{
	hdcMemory=NULL;
	hbmOldBitMap=NULL;
	hbmNewBitMap=NULL;
	iWidth=0;
	iHeight=0;
}
BitMapObject::~BitMapObject(){
	if(hdcMemory)Destroy();
}
void BitMapObject::Load(HDC hdcCompatible, HBITMAP hLoad){
	if(hdcMemory)Destroy();
	hdcMemory=CreateCompatibleDC(hdcCompatible);
	hbmNewBitMap=hLoad;
	hbmOldBitMap=(HBITMAP)SelectObject(hdcMemory,hbmNewBitMap);
	BITMAP bmp;
	GetObject(hbmNewBitMap,sizeof(BITMAP),(LPVOID)&bmp);
	iWidth=bmp.bmWidth;
	iHeight=bmp.bmHeight;
}
void BitMapObject::Create(HDC hdcCompatible, int width, int height){
	if(hdcMemory)Destroy();
	hdcMemory=CreateCompatibleDC(hdcCompatible);
	hbmNewBitMap=CreateCompatibleBitmap(hdcCompatible,width,height);
	hbmOldBitMap=(HBITMAP)SelectObject(hdcMemory,hbmNewBitMap);
	iWidth=width;
	iHeight=height;
}
void BitMapObject::-)estroy(){
	SelectObject(hdcMemory,hbmOldBitMap);
	DeleteObject(hbmNewBitMap);
	DeleteDC(hdcMemory);
	hdcMemory=NULL;
	hbmOldBitMap=NULL;
	hbmNewBitMap=NULL;
	iWidth=0;
	iHeight=0;
}
BitMapObject::operator HDC(){
	return(hdcMemory);
}
int BitMapObject::GetWidth(){
	return(iWidth);
}
int BitMapObject::GetHeight(){
	return(iHeight);
}

class CBouncyBall
{
	private:
	float x,y;
	float vx,vy;
	public:
	CBouncyBall();
	~CBouncyBall();
	bool SetX(float nx);
	bool SetY(float ny);
	float GetX();
	float GetY();
	float GetVX();
    float GetVY();
	bool SetVX(float nvx);
	bool SetVY(float nvy);
};
CBouncyBall::CBouncyBall(){
	x=y=0;
	vx=vy=0;
}
CBouncyBall::~CBouncyBall(){
	x=y=0;
	vx=vy=0;
}
float CBouncyBall::GetX(){
	return(x);
}
float CBouncyBall::GetY(){
	return(y);
}
bool CBouncyBall::SetX(float nx){
	x=nx;
	return(true);
}
bool CBouncyBall::SetY(float ny){
	y=ny;
	return(true);
}
bool CBouncyBall::SetVX(float nvx){
	vx=nvx;
	return(true);
}
bool CBouncyBall::SetVY(float nvy){
	vy=nvy;
	return(true);
}
float CBouncyBall::GetVX(){
	return(vx);
}
float CBouncyBall::GetVY(){
	return(vy);
}

bouncy_resource.rc:
#include "bouncy_resource.h"

MAIN_MENU MENU
{
    MENUITEM "&Close" MENUID_CLOSE
}

bouncy_resource.h:
#define MENUID_CLOSE 1001
#define MAIN_MENU 1000


[Edited by - Coder on September 1, 2005 6:26:26 PM]

Share this post


Link to post
Share on other sites
Advertisement
Hey,

First, you should change those 'quote' tags to 'source' tags; makes things much easier to read.

Second, can you clarrify what the 'weird random graphic errors' are? A screen shot would be awesome. From what you've said, it sounds like you may just not be clearing your back buffer.

Matt Hughson

Share this post


Link to post
Share on other sites
If I remember correctly, you should blit to back buffer to the front. I found a source code example of a windowed DirectDraw 7 app for you on the net (www.codeguru.com). It should show you how to use the Blt correctly in windowed mode. It's written in C++ so I hope that the classes and stuff don't confuse you.


// DDrawSystem.h: interface for the CDDrawSystem class.
//
////////////////////////////////////////////////////////////////

#if !defined(AFX_DDRAWSYSTEM_H__1E152EB4_ED1D_4079_BDD4_773383DD98C8
__INCLUDED_)
#define AFX_DDRAWSYSTEM_H__1E152EB4_ED1D_4079_BDD4_773383DD98C8
__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <ddraw.h>

#define _CHARACTORBUILDER_
#include "../GameLib/Image.h"

class CDDrawSystem
{
public:
CDDrawSystem();
virtual ~CDDrawSystem();

BOOL Init(HWND hWnd);
void Terminate();
void Clear();
void TestDraw(int x, int y);
void Display();

protected:
LPDIRECTDRAW7 m_pDD;
LPDIRECTDRAWSURFACE7 m_pddsFrontBuffer;
LPDIRECTDRAWSURFACE7 m_pddsStoreBuffer;
LPDIRECTDRAWCLIPPER pcClipper;

HWND hWnd;
};

#endif

//!defined(AFX_DDRAWSYSTEM_H__1E152EB4_ED1D_4079_BDD4_
773383DD98C8__INCLUDED_)
// DDrawSystem.cpp: implementation of the CDDrawSystem class.
//
////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "DDrawSystem.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif


////////////////////////////////////////////////////////////////
// Construction/Destruction
////////////////////////////////////////////////////////////////

CDDrawSystem::CDDrawSystem()
{
m_pDD = NULL;
m_pddsFrontBuffer = NULL;
m_pddsStoreBuffer = NULL;
pcClipper = NULL;
}

CDDrawSystem::~CDDrawSystem()
{
Terminate();
}

// old DirectDraw Initialization stuff.
// Set a window mode DirectDraw Display.
BOOL CDDrawSystem::Init(HWND hWnd)
{
HRESULT hRet;

this->hWnd = hWnd;

hRet = DirectDrawCreateEx(NULL, (VOID**)&m_pDD,
IID_IDirectDraw7, NULL);

if(hRet != DD_OK)
{
AfxMessageBox("Failed to create directdraw object.");
return FALSE;
}

hRet = m_pDD->SetCooperativeLevel(hWnd, DDSCL_NORMAL);
if(hRet != DD_OK)
{
AfxMessageBox("Failed to set directdraw display behavior.");
return FALSE;
}

HRESULT hr;

DDSURFACEDESC2 ddsd;
ZeroMemory( &ddsd, sizeof( ddsd ) );
ddsd.dwSize = sizeof( ddsd );
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;

if(FAILED(hr = m_pDD->CreateSurface(&ddsd,
&m_pddsFrontBuffer, NULL)))
{
AfxMessageBox("Failed to create primary surface.");
return FALSE;
}


// Create the backbuffer surface
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN |
DDSCAPS_3DDEVICE;
ddsd.dwWidth = 800;
ddsd.dwHeight = 600;

if(FAILED(hr = m_pDD->CreateSurface(&ddsd,
&m_pddsStoreBuffer, NULL)))
{
AfxMessageBox("Failed to create back buffer surface.");
return FALSE;
}

if(FAILED(hr = m_pDD->CreateClipper(0, &pcClipper, NULL)))
{
AfxMessageBox("Failed to create clipper.");
return FALSE;
}

if(FAILED(hr = pcClipper->SetHWnd(0, hWnd)))
{
pcClipper->Release();
AfxMessageBox("Failed to create primary surface.");
return FALSE;
}

if(FAILED(hr = m_pddsFrontBuffer->SetClipper(pcClipper)))
{
pcClipper->Release();
AfxMessageBox("Failed to create primary surface.");
return FALSE;
}

return TRUE;
}

// make sure all things are terminated and set to NULL
// when application ends.
void CDDrawSystem::Terminate()
{
if (m_pDD != NULL)
{
if (m_pddsFrontBuffer != NULL)
{
if (m_pddsStoreBuffer != NULL)
{
m_pddsStoreBuffer->Release();
m_pddsStoreBuffer = NULL;
}

if (pcClipper != NULL)
{
pcClipper->Release();
pcClipper = NULL;
}

m_pddsFrontBuffer->Release();
m_pddsFrontBuffer = NULL;
}
m_pDD->Release();
m_pDD = NULL;
}
}

// clear both off csreen buffer and primary buffer.
void CDDrawSystem::Clear()
{
HRESULT hRet;
DDBLTFX fx;
fx.dwSize = sizeof(fx);
fx.dwFillColor = 0x000000;

while (1)
{
hRet = m_pddsFrontBuffer->Blt(NULL, NULL, NULL,
DDBLT_COLORFILL, &fx);
if (hRet == DD_OK)
break;
else if (hRet == DDERR_SURFACELOST)
{
m_pddsFrontBuffer->Restore();
}
else if (hRet != DDERR_WASSTILLDRAWING)
break;
}

while (1)
{
hRet = m_pddsStoreBuffer->Blt(NULL, NULL, NULL,
DDBLT_COLORFILL, &fx);
if (hRet == DD_OK)
break;
else if (hRet == DDERR_SURFACELOST)
{
m_pddsStoreBuffer->Restore();
}
else if (hRet != DDERR_WASSTILLDRAWING)
break;
}
}

// a test:
// The conclusion is: Under no circumstance, draw directly to
// primary Surface!
// It doesn't work that way.
// ...
// ...
// This is just a simple test function. It has shit use in this
// project.

void CDDrawSystem::TestDraw(int x, int y)
{
HRESULT hRet;
HDC dc;
hRet = m_pddsStoreBuffer->GetDC(&dc);
if (hRet != DD_OK)
return;

POINT p = {0 + x, 0 + y};
ClientToScreen(hWnd, &p);

SetTextColor(dc, RGB(255, 0, 0));
TextOut(dc, 20, 20, "This is a stinky App", lstrlen("This is
a stinky App"));

Ellipse(dc, x-50, y-50, x+50,y+50);

m_pddsStoreBuffer->ReleaseDC(dc);
}

// Load images from offscteen buffer to primary buffer
// and for display.
void CDDrawSystem::Display()
{
HRESULT hRet;

RECT rt;
POINT p = {0, 0};
ClientToScreen(hWnd, &p);
rt.left = 0 + p.x;
rt.top = 0 + p.y;
rt.right = 800 + p.x;
rt.bottom = 600 + p.y;

while(1)
{
hRet = m_pddsFrontBuffer->Blt(&rt, m_pddsStoreBuffer,
NULL, DDBLT_WAIT, NULL);
if (hRet == DD_OK)
break;
else if(hRet == DDERR_SURFACELOST)
{
m_pddsFrontBuffer->Restore();
m_pddsStoreBuffer->Restore();
}
else if(hRet != DDERR_WASSTILLDRAWING)
return;
}
}


Share this post


Link to post
Share on other sites
You just need to clear the backbuffer (using a Blt with DDBLT_COLORFILL) before drawing to it.

Share this post


Link to post
Share on other sites
Oh works now, thanks
ehm i got another problem

bool DrawAll(){

if(!Bouncy_ClearBack())return(false);
int x,y,Linewidth;
UCHAR *VRam;
DDSURFACEDESC2 ddsd;
HRESULT ddrval;
ZeroMemory(&ddsd,sizeof(ddsd));
ddsd.dwSize=sizeof(ddsd);
lpDDSBack->Lock(NULL,&ddsd,DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT,NULL);
Linewidth=ddsd.lPitch;
VRam=(UCHAR *)ddsd.lpSurface;
for(x=0;x<500;x++){
for(y=0;y<10;y++){
VRam[x+(y*Linewidth)]=234;
}
}
lpDDSBack->Unlock(NULL);
Bouncy_Flip();
return(true);
}



thats my ne drawall

and thats my new clearback:

bool Bouncy_ClearBack(void){
HRESULT ddrval;
DDBLTFX fx;
fx.dwSize=sizeof(fx);
fx.dwFillColor=0xFFFFFF;
ddrval=lpDDSBack->Blt(NULL,NULL,NULL,DDBLT_COLORFILL|DDBLT_WAIT,&fx);
if(ddrval==DD_OK)return(true);
else{
if(ddrval==DDERR_SURFACELOST){
lpDDSBack->Restore();
ddrval=lpDDSBack->Blt(NULL,NULL,NULL,DDBLT_COLORFILL|DDBLT_WAIT,&fx);
if(ddrval==DD_OK)return(true);else return(false);
}
}
return(true);
}



why it dont fills the entire window with the color
i mean its 500 x , the window is only 400 width
O.o it wont work with 400 or 300 either

Share this post


Link to post
Share on other sites
Because your code assumes there is one byte per pixel. If your screen color resolution is 32-bits, then there are actually 4 bytes per pixel. In 16-bits, there would be 2 bytes per pixel.

Share this post


Link to post
Share on other sites
uhm is there no way to make it 8-bit O.o
without changing the whole's screen resolution =/
come on... directx/windows has for everything a function lol

Share this post


Link to post
Share on other sites
Yep. That would do it. Then you can either declare your VRam as a 16/32-bit pointer, or set the individual bytes directly through the UCHAR *. If you change your pointer declaration, you can still use same indexing you have now. If not, you will need to multiply your indices by the number of bytes per pixel.

Share this post


Link to post
Share on other sites
You have VRam declared as UCHAR *. If you change that to UINT * or DWORD * (depending on 16- or 32-bit), then you can use the same indexing scheme you have now (row * width + col). If you leave it a UCHAR *, then you have to use multiply your index by 2 or 4.

Share this post


Link to post
Share on other sites

bool DrawAll(){

if(!Bouncy_ClearBack())return(false);
int x,y,Linewidth;
UINT *VRam;
DDSURFACEDESC2 ddsd;
HRESULT ddrval;
ZeroMemory(&ddsd,sizeof(ddsd));
ddsd.dwSize=sizeof(ddsd);
lpDDSBack->Lock(NULL,&ddsd,DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT,NULL);
Linewidth=ddsd.lPitch;
VRam=(UINT *)ddsd.lpSurface;
for(x=0;x<400;x++){
for(y=0;y<10;y++){
VRam[x+(y*Linewidth)]=235;
}
}
lpDDSBack->Unlock(NULL);
Bouncy_Flip();
return(true);
}

like this? =/
now i have some weird blue lines xD

Share this post


Link to post
Share on other sites
Sorry, I didn't notice that Linewidth was set to the lPitch. lPitch is the number of bytes per row. Since you've used UINT * for your pointer, you need to divide the lPitch by 2 to get the number of UINTs per line.

Also, to get the color you want, you have to play some games. Take a look at this article. It describes how to determine the number of bits per color for your 16-bit mode and then convert individual red/green/blue values into a 16-bit color value.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement