Thread: Test App crashes when writing to primary surface using directdraw

  1. #1
    Registered User
    Join Date
    Jan 2003
    Posts
    14

    Smile Test App crashes when writing to primary surface using directdraw

    I am new to C++. (I hate it and would prefer using plain C, but can't figure out how to use plain C and directx or directdraw. ) I am going through the tuts from http://sunlightd.virtualave.net/Wind...irstSteps.html and everything works fine until I make my changes. What I am trying to do is write text directly to the primary surface, which if I understand correctly in the code below should be the desktop window. But when I run my mangled example code it crashes, and I can't figure out why. Maybe I should just finish the rest of the tutorail before I start playing around? Well anyways some advice and knowledge would be much appreciated. I don't want anyone to code anything for me, just tell me what I am (probably obviously) doing wrong, please.

    Code:
    ////////////////////////////////////////////////////////////////////////////////
    // DirectDrawBones.cpp
    //
    //  DirectDraw bare-bones application.
    #include "stdafx.h"
    #include <windows.h>
    #include <ddraw.h>
    
    HWND hWndMain;
    IDirectDraw7		*pDD;
    IDirectDrawSurface7	*lpPrimary, *lpBackBuffer;
    
    // Initialise DirectDraw and go to full screen mode.
    void InitDirectDraw()
    {
    HDC hdc;
    
    	// Create the DirectDraw object, through which we will create surfaces.
    	DirectDrawCreateEx(NULL, (void **)&pDD, IID_IDirectDraw7, NULL);
    
    	// Set the co-operative level to exclusive and full-screen.
    	pDD->SetCooperativeLevel(hWndMain, DDSCL_NORMAL | DDSCL_ALLOWREBOOT);
    	//	pDD->SetCooperativeLevel(hWndMain, 
    	//	DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT);
    
    	// Set the display mode to 640x480, 16-bit colour, default refresh rate.
    	//pDD->SetDisplayMode(640, 480, 16, 0, 0);
    
    	DDSURFACEDESC2	ddsd;
    
    	// Create the primary surface with two back buffers.
    	ZeroMemory(&ddsd, sizeof(DDSURFACEDESC2));
    	ddsd.dwSize = sizeof(DDSURFACEDESC2);
    	ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
    	ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDCAPS_GDI; 
    	ddsd.dwBackBufferCount = 1;
    	pDD->CreateSurface(&ddsd, &lpPrimary, NULL);
    	
    	// Get the back buffer pointer, to which we will do all drawing.
    	ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
    	lpPrimary->GetAttachedSurface(&ddsd.ddsCaps, &lpBackBuffer);
    	if (lpPrimary->GetDC(&hdc) == DD_OK) 
    { 
        SetBkColor(hdc, RGB(0, 0, 255)); 
        SetTextColor(hdc, RGB(255, 255, 0)); 
        TextOut(hdc, 0, 400, "hello!", lstrlen("hello!")); 
        lpPrimary->ReleaseDC(hdc);
    } 
    }
    
    void ExitDirectDraw()
    {
    	// Release the primary surface. Note that the back buffer is automatically released 
    	//  (since it was created at the same time).
    	lpPrimary->Release();
    	lpPrimary = NULL;
    
    	// Release the DirectDraw object.
    	pDD->Release();
    	pDD = NULL;
    }
    
    // Handle all messages for the main window.
    LRESULT CALLBACK MainWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
    	switch (uMsg)
    	{
    	case WM_CLOSE:
    		ExitDirectDraw();
    		DestroyWindow(hWnd);
    		return 0;
    
    	case WM_DESTROY:
    		PostQuitMessage(0);
    		return 0;
    	}
    	return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    
    // Register the window class for the main window.
    void RegisterWindowClass()
    {
    	WNDCLASSEX	wcx;
    
    	ZeroMemory(&wcx, sizeof(WNDCLASSEX));
    	wcx.cbSize = sizeof(WNDCLASSEX);
    	wcx.lpfnWndProc = MainWindowProc;
    	wcx.hInstance = GetModuleHandle(NULL);
    	// Windows-default icon. Replace with your own.
    	wcx.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    	wcx.hCursor = NULL;
    	// Black background for the window.
    	wcx.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
    	wcx.lpszMenuName = NULL;
    	wcx.lpszClassName = "SampleWindowClass";
    	RegisterClassEx(&wcx);
    }
    
    // Idle-time processing function.
    
    void OnIdle(void)
    {
    }
    
    // Program entry point.
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int) 
    {
    	MSG	msg;
    
    	RegisterWindowClass();
    
    	// Create a window that fills the screen.
    	hWndMain = CreateWindowEx(WS_EX_APPWINDOW,
    		"SampleWindowClass", "DirectDraw Bare-Bones Sample", WS_POPUP,
    		0, 0, 200, 200,
    		NULL, NULL, hInstance, NULL);
    	
    	ShowWindow(hWndMain, SW_SHOW);
    
    	InitDirectDraw();
    
    	// Message loop. Note that this has been modified to allow
    	//  us to execute even if no messages are being processed.
    	for (;;)
    	{
    		if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
    		{
    			if (!GetMessage(&msg, NULL, 0, 0))
    				break;
    			
    			// If you want WM_CHAR messages, add
    			//  TranslateMessage(&msg);
    			DispatchMessage(&msg);
    		}
    		
    		// Idle-time processing
    		OnIdle();
    	}
    
    	return 0;
    }
    Thanks,
    Emonk

    *EDIT- Apparently I posted this in the wrong board, because it got moved. Sorry to whoever had to move it.
    Last edited by emonk; 08-13-2003 at 09:42 AM.

  2. #2
    Registered User
    Join Date
    Jan 2003
    Posts
    14

    Debugging

    OK, I've never used the debugger before, but I just tried it, and it shows that at the time my app crashes, lpPrimary is NULL (actually 000000(whole bunch O' nuttin)). This looks like the problem to me, but why is lpPrimary NULL? Also if anyone knows of a good tute about how to use the debugger, I would much appreciate it (I'm using VS6).

  3. #3
    Registered User
    Join Date
    Jan 2003
    Posts
    14
    OK, I have figured out what was causing the crash. The primary surface was not being created (my call to CreateSurface failed), and I have even figured out how to fix it. I changed this
    Code:
    ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
    to this
    Code:
    ddsd.dwFlags = DDSD_CAPS;
    So there must be something wrong with the way I am handling the backbuffers. I just dont understand what I am doing wrong, and why it is wrong. Can someone please enlighten me?

  4. #4
    Registered User
    Join Date
    Jan 2003
    Posts
    14
    OK, I guess to talking to myself isn't much fun, but here comes some more.

    I have figured out what I was (obviously) doing wrong at first. I needed to just create a backbuffer of the 'DDSCAPS_OFFSCREENPLAIN' type. and use that. Also you have to have DDSCAPS_COMPLEX if you want to do flipping, and it has to be in fullscreen exclusive mode.
    So after reading,and reading,and reading to figure that out (Those darm CHM help files that come with the SDK suck, I like the old .hlp ones better.) I am now stuck with the Lock function. if I do something like
    Code:
    rval = lpPrimary->Lock(NULL,&ddsd,DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,lpPrimary);
    it returns DD_OK, but other apps (GDI, and normal windows junk) can still overwrite my windows text, or if Im in exclusive mode, the whole screen. It's very frustarting when windows returns an error code that says it worked but it didn't really. Here is the code from above modified to 1.)work and
    2.)Lock the Primary surface.
    If it was working correctly than It would make windows unusable, so careful. This is just test code. I am trying to understand what the heck is going on here, but its not easy (for me :) ).
    Code:
    #include "stdafx.h"
    #include <windows.h>
    #include <ddraw.h>
    
    HWND hWndMain;
    IDirectDraw7		*pDD;
    IDirectDrawSurface7	*lpPrimary, *lpBackBuffer;
    
    // Initialise DirectDraw
    void InitDirectDraw()
    {
    HDC hdc;
    RECT FromRect;
    DDBLTFX ddbltfx;
    DDPIXELFORMAT ddpf; 
    DDCOLORKEY ddck;
    HRESULT rval;
    
    	// Create the DirectDraw object, through which we will get the primary surface.
    	DirectDrawCreateEx(NULL, (void **)&pDD, IID_IDirectDraw7, NULL);
    
    	// Set the co-operative level to exclusive and full-screen.
    	pDD->SetCooperativeLevel(hWndMain, DDSCL_NORMAL);
    
    	DDSURFACEDESC2	ddsd;
    
    	// Create the primary surface.
    	ZeroMemory(&ddsd, sizeof(DDSURFACEDESC2));
    	ddsd.dwSize = sizeof(DDSURFACEDESC2);
    	ddsd.dwFlags = DDSD_CAPS;
    	ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
    	pDD->CreateSurface(&ddsd, &lpPrimary, NULL);
    	
    	//Create a backbuffer.
    	ZeroMemory(&ddsd, sizeof(DDSURFACEDESC2));
    	ddsd.dwSize = sizeof(DDSURFACEDESC2);
    	ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
    	ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
    	ddsd.dwWidth = 50;
    	ddsd.dwHeight = 50;
    	pDD->CreateSurface(&ddsd, &lpBackBuffer, NULL);
    
    //Make sure Our Buffers got made correctly
    	if (lpPrimary == NULL){
    		MessageBox(NULL,NULL,"Error! lpPrimary is NULL!",NULL);
    		exit(1);
    	}
    	
    	if (lpBackBuffer == NULL){
    		MessageBox(NULL,NULL,"Error! lpBackBuffer is NULL!",NULL);
    		exit(1);
    	}
    //Clear the back buffer
    ddpf.dwSize = sizeof(ddpf);
    lpBackBuffer->GetPixelFormat(&ddpf);
    
        ddbltfx.dwSize = sizeof(ddbltfx); 
        ddbltfx.dwFillColor = 0xff; // Pure blue
        lpBackBuffer->Blt( NULL,NULL,NULL,DDBLT_COLORFILL,&ddbltfx); 
    
    //Write some text to the BackBuffer
    	if (lpBackBuffer->GetDC(&hdc) == DD_OK) 
    { 
        SetBkColor(hdc, RGB(0, 0, 255)); 
        SetTextColor(hdc, RGB(0, 0, 0)); 
        TextOut(hdc, 0, 0, "hello!", lstrlen("hello!")); 
        lpBackBuffer->ReleaseDC(hdc);
    }
    //Set Up Blt
    	ddck.dwColorSpaceLowValue = 0xff;
    	ddck.dwColorSpaceHighValue = 0xff;
    	lpBackBuffer->SetColorKey( DDCKEY_SRCBLT, &ddck );
    	FromRect.left = 0;
    	FromRect.top = 0;
    	FromRect.right = 50;
    	FromRect.bottom= 50;
    //Blt From Offscreen Buffer to Primary Surface
    	lpPrimary->BltFast(0,400,lpBackBuffer,&FromRect,DDBLTFAST_SRCCOLORKEY);
    	rval = lpPrimary->Lock(NULL,&ddsd,DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,lpPrimary);
    	if (rval != DD_OK){
    		MessageBox(NULL,NULL,"Lock Failed!",NULL);
    	}
    	//lpPrimary->Unlock(rval);
    }
    
    void ExitDirectDraw()
    {
    	// Release the primary surface. 
    	lpPrimary->Release();
    	lpPrimary = NULL;
    
    	// Release the DirectDraw object.
    	pDD->Release();
    	pDD = NULL;
    }
    
    // Handle all messages for the main window.
    LRESULT CALLBACK MainWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
    	switch (uMsg)
    	{
    	case WM_CLOSE:
    		ExitDirectDraw();
    		DestroyWindow(hWnd);
    		return 0;
    
    	case WM_DESTROY:
    		PostQuitMessage(0);
    		return 0;
    	}
    	return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    
    
    // Program entry point.
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int) 
    {
    	MSG	msg;
    
    	InitDirectDraw();
    
    //Start Message Loop
    	while (GetMessage(&msg, NULL, 0, 0))
    		DispatchMessage(&msg);
    
    	return 0;
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Another weird error
    By rwmarsh in forum Game Programming
    Replies: 4
    Last Post: 09-24-2006, 10:00 PM
  2. Cannot find error
    By rwmarsh in forum Game Programming
    Replies: 6
    Last Post: 09-20-2006, 06:48 AM
  3. C++ Operator Overloading help
    By Bartosz in forum C++ Programming
    Replies: 2
    Last Post: 08-17-2005, 12:55 PM
  4. counting program worked, but test file CRASHES IT.. WHY?
    By Unregistered in forum C++ Programming
    Replies: 6
    Last Post: 05-19-2002, 02:29 AM
  5. writing to a structure via pointer crashes...
    By Unregistered in forum C Programming
    Replies: 4
    Last Post: 12-17-2001, 10:25 AM