Advertisement

Problems creating primary surface... And my app won't close?!

Started by January 08, 2003 08:00 AM
2 comments, last by MainForze 21 years, 10 months ago
Heya! I've been trying to code this DirectX 7 app (it only uses DirectDraw) but for some reason the primary surface doesn't show... The resolution changes, but still the regular GDI shows... I've checked the return values from CreateSurface and GetAttachedSurface but they both return 0 (DD_OK)... Also... The program doesn't properly shutdown. The window gets destroyed and the program's icon is removed from the taskbar, but after closing the CTRL-ALT-DEL menu says a program called "Directx" is still running, and when I recompile I get a linker error saying it can't write to the .exe file...? Here's the (only) source-file, there are extra comments in it...
    
//-------------------------------------------------------------------------------------------

//                                          Defines

//-------------------------------------------------------------------------------------------


#define WIN32_LEAN_AND_MEAN // leave out MFC stuff
#define DIRECTDRAW_VERSION 0x0700 // Use DirectX 7


//-------------------------------------------------------------------------------------------

//                                          Includes

//-------------------------------------------------------------------------------------------


#include <windows.h> // includes windows.h
#include <ddraw.h> // includes ddraw.h


//-------------------------------------------------------------------------------------------

//                                          Globals

//-------------------------------------------------------------------------------------------


struct
{
	char	             szTitle[33];
	DWORD                dwWidth;
	DWORD                dwHeight;
	DWORD                dwBPP;
	LPDIRECTDRAW7	     lpDD;
	LPDIRECTDRAWSURFACE7 lpDDSPrimary;
	LPDIRECTDRAWSURFACE7 lpDDSBack;
	DDSURFACEDESC2	     ddSurfDesc;
	DDSCAPS2	     ddSurfCaps;
} g;

//-------------------------------------------------------------------------------------------

//                                    Function Prototypes

//-------------------------------------------------------------------------------------------


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iShowCmd);
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam);
int mbprintf(UINT iStyle, char * szCaption, char * szFormat, ...);
int InitDD(HWND hWnd, DWORD dwWidth, DWORD dwHeight, DWORD dwBPP);
void TermDD();
void MainLoop();

//-------------------------------------------------------------------------------------------

//                                   Function Implementations

//-------------------------------------------------------------------------------------------


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iShowCmd)
{
	// Partially fill global struct with required values

	strcpy(g.szTitle, "DirectX Tryout"); // Window title and classname

	g.dwWidth = 800; // Horizontal resolution

	g.dwHeight = 600; // Vertical res.

	g.dwBPP = 32; // Bits per pixel


	// Create and register window class

	WNDCLASSEX wc;
	wc.cbSize = sizeof(wc);
	wc.style = CS_HREDRAW | CS_VREDRAW;
	wc.lpfnWndProc = WndProc;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hInstance = hInstance;
	wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
	wc.lpszMenuName = NULL;
	wc.lpszClassName = g.szTitle;
	wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
	RegisterClassEx(&wc);

	// Create window based on window class and show it

	HWND hWnd = CreateWindowEx(NULL, (char *)&g.szTitle, (char *)&g.szTitle, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT, (int)g.dwWidth, (int)g.dwHeight, NULL, NULL, hInstance, NULL);
	ShowWindow(hWnd, iShowCmd);

	// Initialize DirectDraw!

	int iddRet = InitDD(hWnd, g.dwWidth, g.dwHeight, g.dwBPP);

//	iddRet = -2; // I put this in for testing purposes, but I noticed that when I use this

	             // the string "Directx" doesn't show up in the CTRL-ALT-DEL menu

	             // after program termination!! This ofcourse leads me to believe that the

	             // error occurs either in the messageloop or in the WndProc, but I have absolutely

	             // no idea what exactly the error is...


	if(iddRet)
	{
		switch(iddRet)
		{
		case -1:
			mbprintf(MB_ICONERROR, g.szTitle, "Couldn't initialize DirectDraw! You need DirectX 7 or higher to run this application.");
			return 0;

		case -2:
			mbprintf(MB_ICONERROR, g.szTitle, "Couldn't set DirectDraw to exclusive fullscreen mode! Please close all other DirectX applications or install updated drivers for your videocard.");
			TermDD();
			return 0;

		case -3:
			mbprintf(MB_ICONERROR, g.szTitle, "Couldn't set another resolution! Please close all other DirectX applications, check your videocard's settings or install updated drivers.");
			TermDD();
			return 0;

		case -4:
			mbprintf(MB_ICONERROR, g.szTitle, "Couldn't create primary surface! Either you don't have enough memory or your videocard is horribly out of date.");
			TermDD();
			return 0;

		case -5:
			mbprintf(MB_ICONERROR, g.szTitle, "Couldn't retrieve a pointer to the backbuffer. Are you sure you have enough memory to run this application?");
			TermDD();
			return 0;
		}
	}

	// Enter messageloop!

	MSG msg;
	while(true)
	{
		if(PeekMessage(&msg, hWnd, NULL, NULL, PM_NOREMOVE)) // There is a message waiting

		{
			if(GetMessage(&msg, NULL, NULL, NULL)) // Message isn't WM_QUIT, so process it

			{
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			}
			else // Message was WM_QUIT, time to exit!

			{
				break;
			}
		}
		else // No message waiting, so call main loop

		{
			MainLoop();
		}
	}
/*
	while(GetMessage(&msg, NULL, NULL, NULL))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
*/

	// Terminate and release DirectDraw object

	TermDD();

	return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
	switch (iMsg) // Check message

	{
	case WM_DESTROY: // Uh oh! Time to Quit!

		PostQuitMessage(0);
		return 0;
	}
	
	return DefWindowProc(hWnd, iMsg, wParam, lParam);
}

int mbprintf(UINT iStyle, char * szCaption, char * szFormat, ...) // NEW! In stores now! MessageBox() function with added printf() functionality!

{
	char szBuffer[1024];
	va_list pArgList;

	va_start(pArgList, szFormat);
	wvsprintf(szBuffer, szFormat, pArgList);

	return MessageBox(NULL, szBuffer, szCaption, iStyle);
}

int InitDD(HWND hWnd, DWORD dwWidth, DWORD dwHeight, DWORD dwBPP)
{
	HRESULT ddReturn = NULL;
	
	// Create DirectDraw object

	DirectDrawCreateEx(NULL, (void **)&g.lpDD, IID_IDirectDraw7, NULL);
	if (ddReturn != DD_OK) return -1;

	// Set DD object to exclusive fullscreen mode

	ddReturn = g.lpDD->SetCooperativeLevel(hWnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
	if (ddReturn != DD_OK) return -2;

	// Set requested displaymode

	ddReturn = g.lpDD->SetDisplayMode(dwWidth, dwHeight, dwBPP, 0, 0);
	if (ddReturn != DD_OK) return -3;

	// Create primary surface with 1 backbuffer

	ZeroMemory(&g.ddSurfDesc, sizeof(g.ddSurfDesc));
	g.ddSurfDesc.dwSize = sizeof(g.ddSurfDesc);
	g.ddSurfDesc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
	g.ddSurfDesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
	g.ddSurfDesc.dwBackBufferCount = 1;
	ddReturn = g.lpDD->CreateSurface(&g.ddSurfDesc, &g.lpDDSPrimary, NULL);
	if(ddReturn != DD_OK) return -4;

	// Get backbuffer surface pointer

	ZeroMemory(&g.ddSurfCaps, sizeof(g.ddSurfCaps));
	g.ddSurfCaps.dwCaps = DDSCAPS_BACKBUFFER;
	ddReturn = g.lpDDSPrimary->GetAttachedSurface(&g.ddSurfCaps, &g.lpDDSBack);
	if (ddReturn != DD_OK) return -5;

	return 0;
}

void TermDD() // No need to comment this, it kind of speaks for itself ;)

{
	if (g.lpDD)
	{
		if (g.lpDDSPrimary)
		{
			g.lpDDSPrimary->Release();
			g.lpDDSPrimary = NULL;
		}

		g.lpDD->RestoreDisplayMode();
		g.lpDD->Release();
		g.lpDD = NULL;
	}
}
void MainLoop()
{

}
    
"It's strange, isn't it? You stand in the middle of a library and go 'AAAAAAAGGHHHH' and everyone just stares at you. But you do the same thing on an airplane, and everyone joins in!"
[edited by - MainForze on January 8, 2003 9:04:20 AM]
"It's strange, isn't it? You stand in the middle of a library and go 'AAAAAAAGGHHHH' and everyone just stares at you. But you do the same thing on an airplane, and everyone joins in!"
to solve the app termination problem, try replacing the hWnd with a NULL in the PeekMessage call.
Advertisement
Thanks AP, I''ll try that. But why would that be the problem? I mean, I don''t only want to know how it works, but WHY it works... But thanks for the suggestion!


"It''s strange, isn''t it? You stand in the middle of a library and go ''AAAAAAAGGHHHH'' and everyone just stares at you. But you do the same thing on an airplane, and everyone joins in!"

"It's strange, isn't it? You stand in the middle of a library and go 'AAAAAAAGGHHHH' and everyone just stares at you. But you do the same thing on an airplane, and everyone joins in!"
an app''s msg queue is tied to a thread, not a window. several msgs get put onto an apps thread''s msg queue w/o a hWnd. one such is the WM_QUIT, which is posted by the PostQuitMessage call. notice that there''s no hWnd passed to that function? your PeekMessage call was asking for only those msgs posted for your main hWnd, so it''s missing the WM_QUIT msg, which means the GetMessage call is bypassed, so you loop forever.

btw, regarding your other problem, i think you''re still seeing the desktop because you''re not doing any flipping with your DD surfaces. in DX7, calling Flip is what gets the backbuffer surface "presented" to the associated window''s device context. if you have the DX7 docs, there''s a pretty good write up on how to go about coding a flip function.

This topic is closed to new replies.

Advertisement