Direct X 7 woes
What is wrong with this??? It runs fine, but then crashes on exit...
------
#define WIN32_LEAN_AN_MEAN
#include
#include
///////////////////////////////////////////////////////////////
LPDIRECTDRAW7 lpdd;
LPDIRECTDRAWSURFACE7 lpddsFront;
LPDIRECTDRAWSURFACE7 lpddsBack;
_int16* lpVideo;
///////////////////////////////////////////////////////////////
VOID ExitOnError(LPSTR error)
{
PostQuitMessage(0);
MessageBox(NULL, error, "ERROR", MB_OK);
};
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CREATE:
{
DDSURFACEDESC2 ddsd;
DDSCAPS2 ddscaps;
if( DirectDrawCreateEx(NULL, (VOID**)&lpdd, IID_IDirectDraw7, NULL) != DD_OK )
ExitOnError("DirectDrawCreateEx failed!");
if( lpdd->SetCooperativeLevel(hWnd, DDSCL_ALLOWREBOOT / DDSCL_EXCLUSIVE / DDSCL_FULLSCREEN) != DD_OK )
ExitOnError("SetCooperativeLevel failed!");
if( lpdd->SetDisplayMode(640, 480, 16, 0, 0) != DD_OK)
ExitOnError("SetDisplayMode failed!");
ZeroMemory(&ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS / DDSD_BACKBUFFERCOUNT;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE / DDSCAPS_FLIP / DDSCAPS_COMPLEX;
ddsd.dwBackBufferCount = 1;
if( lpdd->CreateSurface(&ddsd, &lpddsFront, NULL) != DD_OK )
ExitOnError("CreateSurface failed!");
ZeroMemory(&ddscaps, sizeof(ddscaps));
ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
if( lpddsFront->GetAttachedSurface(&ddscaps, &lpddsBack) != DD_OK )
ExitOnError("GetAttachedSurface failed!");
return 0;
} break;
case WM_DESTROY:
{
if( lpddsFront )
lpddsFront->Release();
if( lpdd )
lpdd->Release();
PostQuitMessage(0);
return 0;
} break;
default: break;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
WNDCLASSEX wc;
wc.cbClsExtra = 0;
wc.cbSize = sizeof(WNDCLASSEX);
wc.cbWndExtra = 0;
wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
wc.hInstance = hInstance;
wc.lpfnWndProc = WndProc;
wc.lpszClassName = "wc";
wc.lpszMenuName = NULL;
wc.style = CS_OWNDC / CS_HREDRAW / CS_VREDRAW;
RegisterClassEx(&wc);
HWND hWnd = CreateWindowEx(WS_EX_TOPMOST,
"wc",
"3D Test",
WS_POPUP,
0,
0,
GetSystemMetrics(SM_CXSCREEN),
GetSystemMetrics(SM_CYSCREEN),
0,
0,
hInstance,
0);
ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd);
ShowCursor(FALSE);
MSG msg;
while(1)
{
if( PeekMessage(&msg, 0, 0, 0, PM_REMOVE) )
{
if( msg.message == WM_QUIT )
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
DDSURFACEDESC2 ddsd;
ZeroMemory(&ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
if( lpddsBack->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR, NULL) != DD_OK )
ExitOnError("Lock failed!");
if( lpddsBack->Unlock(NULL) != DD_OK)
ExitOnError("Unlock failed!");
}
return msg.wParam;
}
I don't know EXACTLY what your bug is, but I do see a couple of things that could possibly cause you some problems.
First, at the beginning, you want to define WIN32_LEAN_AND_MEAN. Your code defines WIN32_LEAN_AN_MEAN (you're missing a D)
Second, I'm not sure if it will be causing you problems, but you should probably set your pointers to NULL after you release them in the WM_DESTROY message.
Last, I could be wrong, but I think that maybe your code is processing an extra lpddsBack->Lock() and unlock even after you have released the primary buffer. You should probably check to make sure that you still have the surface before you try to lock or unlock it. I BELIEVE that after your WM_DESTROY message is processed, your loop will try to run one more iteration before getting the WM_QUIT message. Your other option would be to place all the calls to Release() after your main loop instead of in the WM_DESTROY message.
I hope that helps you out.
Edited by - jaxson on 2/28/00 8:20:31 PM
First, at the beginning, you want to define WIN32_LEAN_AND_MEAN. Your code defines WIN32_LEAN_AN_MEAN (you're missing a D)
Second, I'm not sure if it will be causing you problems, but you should probably set your pointers to NULL after you release them in the WM_DESTROY message.
Last, I could be wrong, but I think that maybe your code is processing an extra lpddsBack->Lock() and unlock even after you have released the primary buffer. You should probably check to make sure that you still have the surface before you try to lock or unlock it. I BELIEVE that after your WM_DESTROY message is processed, your loop will try to run one more iteration before getting the WM_QUIT message. Your other option would be to place all the calls to Release() after your main loop instead of in the WM_DESTROY message.
I hope that helps you out.
Edited by - jaxson on 2/28/00 8:20:31 PM
I think the bug is because of the lock/unlock code in your WinMain function. In the message loop, you delete the Direct Draw stuff on WM_DESTROY messages. But after the message takes place, you still try to execute code that tries to lock and unlock a non-existing back surface (which was deleted back in the WM_DESTROY). Calling methods of non-existing COM objects will cause crashes. Put that lock/unlock stuff in its own function and put some kind of check so you do not call that function after the program has started shutting down.
There are some other things you want to look out for:
if( lpddsFront )
lpddsFront->Release();
When COM objects are released, they do not become null. That means if lpddsFront was released somewhere else (or failed to init in the first place), this code will try to release it again, and will cause a nasty GPF. To make sure this does not happen, make sure lpddsFront and other COM objects are set to null first thing, and set them to null after you release them.
... lpddsBack->Unlock(NULL) != DD_OK
COM methods can return a number of return values that do not equal DD_OK, but still indicate a error did not occur. You should have code like this:
... !SUCCEEDED(lpddsBack->Unlock(NULL))
Grandpa Simpson - "I never thought I could shoot down a German plane, but last year I proved myself wrong!"
There are some other things you want to look out for:
if( lpddsFront )
lpddsFront->Release();
When COM objects are released, they do not become null. That means if lpddsFront was released somewhere else (or failed to init in the first place), this code will try to release it again, and will cause a nasty GPF. To make sure this does not happen, make sure lpddsFront and other COM objects are set to null first thing, and set them to null after you release them.
... lpddsBack->Unlock(NULL) != DD_OK
COM methods can return a number of return values that do not equal DD_OK, but still indicate a error did not occur. You should have code like this:
... !SUCCEEDED(lpddsBack->Unlock(NULL))
Grandpa Simpson - "I never thought I could shoot down a German plane, but last year I proved myself wrong!"
---Grandpa Simpson - "I never thought I could shoot down a German plane, but last year I proved myself wrong!"
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement
Recommended Tutorials
Advertisement