Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Help with GetDC, it's crashing my comp...

259 views
Skip to first unread message

Ricky Ip

unread,
Dec 9, 1998, 3:00:00 AM12/9/98
to
Hi. I am have some nasty problems with GetDC with a DirectDraw surface.
When I make a GetDC call, not only does it crash the program, but all of
Windows 95 locks up and I am forced to reboot. I am attempting to get the
device context of my back buffer but when I make the GetDC call, I don't
even get a return value but instead, Windows 95 crashes on me. I never
lock or unlock my surfaces so there should be no conflict when GetDC locks
my surface.

To simplify my problem for anybody that would like to help, I've tried
getting the device context of the primary surface in the "Inawin" program
from the sdk that came with the book "Inside DirectX." The "Inawin"
program came with the DirectX sdk, in the directory "code\chap12\inawin".
Ironically, when I try to get a device context for the primary surface in
"Inawin," it also crashes Windows 95 on me. A snippet of the "Inawin"
code with the GetDC code that I added is below:

-----------------------------------------------------------------------------
// Create the DirectDraw object.
if ( FAILED( DirectDrawCreate( NULL, &lpDD, NULL ) ) )
{
return Fail( hwnd, "Couldn't create DirectDraw object.\n" );
}

// Set normal cooperative level.
if ( FAILED( lpDD->SetCooperativeLevel( hwnd, DDSCL_NORMAL ) ) )
{
return Fail( hwnd, "Couldn't set cooperative level.\n" );
}

// Create the primary surface.
ddsd.dwSize = sizeof( ddsd );
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;

if ( FAILED( lpDD->CreateSurface( &ddsd, &lpDDSPrimary, NULL ) ) )
{
return Fail( hwnd, "Couldn't create primary surface.\n" );
}

...
...

// Check the surface format.
ddpf.dwSize = sizeof( ddpf );
if ( FAILED( lpDDSPrimary->GetPixelFormat( &ddpf ) ) )
{
return Fail( hwnd, "Couldn't get pixel format.\n" );
}

if ( ddpf.dwFlags & DDPF_PALETTEINDEXED8 )
{
// We are palettized, so create a palette and attach it to
// the primary surface.
lpDDPalette = DDLoadPalette( lpDD, "donut.bmp" );

if ( FAILED( lpDDSPrimary->SetPalette( lpDDPalette ) ) )
{
return Fail( hwnd, "Couldnt' get and/or set the palette.\n" );
}
}

//Insert GetDC test code here - this code is not part of the
// original Inawin program
HDC hdc;
// The call to GetDC crashes here!!
if ( FAILED( lpDDSPrimary -> GetDC(&hdc) )) {
return FALSE;
}
// This call is never reached since the program crashes in the call above
lpDDSPrimary->ReleaseDC( hdc );


-----------------------------------------------------------------------------


Ricky.

PS. The entire chapter 13 inawin code from "Inside DirectX" with the
GetDC code that I added is below this line
--------------------------------------------------------------------------

#define NAME "Inawin"
#define TITLE "Inawin"

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <windowsx.h>
#include <ddraw.h>
#include "ddutil.h"

LPDIRECTDRAW lpDD; // DirectDraw object.
LPDIRECTDRAWSURFACE lpDDSPrimary; // DirectDraw primary.
LPDIRECTDRAWSURFACE lpDDSDonut; // DirectDraw surface.
LPDIRECTDRAWPALETTE lpDDPalette; // DirectDraw palette.
LPDIRECTDRAWCLIPPER lpDDClipper; // DirectDraw clipper.
BOOL bActive; // Application status.

RECT rcWindow; // Current client area.
HWND hWndMain;

DWORD dwFrame; // Current sprite frame.
DWORD dwLastTickCount; // Last frame time.

#define DELAY 15 // Frame delay.

// Uncomment the next line to turn off clipping.
// #define NOCLIPPER

static void ReleaseObjects( void )
{
if ( lpDD != NULL )
{
// Our clipper destroys itself automatically
// when we release the primary surface.
if ( lpDDSPrimary != NULL )
{
lpDDSPrimary->Release();
lpDDSPrimary = NULL;
}
// Releasing the primary first insures that
// the palette will destroy itself.
if ( lpDDPalette != NULL )
{
lpDDPalette->Release();
lpDDPalette = NULL;
}

lpDD->Release();
lpDD = NULL;
}
}

BOOL Fail( HWND hwnd, char *szMsg )
{
ReleaseObjects();
OutputDebugString( szMsg );
DestroyWindow( hwnd );
return FALSE;
}

long FAR PASCAL WindowProc( HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam )
{
switch ( message )
{
case WM_MOVE:
// Our window position has changed, so
// get the client (drawing) rectangle.
GetClientRect( hWnd, &rcWindow );
// Convert the coordinates from client relative
// to screen relative.
ClientToScreen( hWnd, ( LPPOINT )&rcWindow );
ClientToScreen( hWnd, ( LPPOINT )&rcWindow + 1 );
return 0;
break;

case WM_SIZE:
// Our window size is fixed, so this could
// only be a minimize or maximize.
if ( wParam == SIZE_MINIMIZED )
{
// We've been minimized, no need to
// redraw the screen.
InvalidateRect( hWnd, NULL, TRUE );
bActive = FALSE;
}
else
{
bActive = TRUE;
}
return 0;
break;

case WM_PALETTECHANGED:
// First check to see if we caused this message.
if ( ( HWND )wParam != hWnd )
{
// We didn't cause it, so we have lost the palette.
OutputDebugString( "Palette lost.\n" );
// Realize our palette.
lpDDSPrimary->SetPalette( lpDDPalette );
// Convert the sprite image to the new palette.
DDReLoadBitmap( lpDDSDonut, "donut.bmp" );
}
break;

case WM_QUERYNEWPALETTE:
// We have control of the palette.
OutputDebugString( "We have the palette.\n" );
lpDDSPrimary->SetPalette( lpDDPalette );
// Convert the sprite image to the new palette.
DDReLoadBitmap( lpDDSDonut, "donut.bmp" );
break;

case WM_KEYDOWN:
switch ( wParam )
{
case VK_ESCAPE:
PostMessage( hWnd, WM_CLOSE, 0, 0 );
break;
}
break;

case WM_DESTROY:
ReleaseObjects();
PostQuitMessage( 0 );
break;

case WM_DISPLAYCHANGE:
OutputDebugString( "A setting has changed.\n" );
break;

case WM_ACTIVATEAPP:
// If we wanted to pause the application when it
// became inactive, we could do so here.
break;

case WM_PAINT:
// We are redrawing every frame so we don't need
// to process this message. If we were using a
// pause screen, we could paint it here.
break;
}

return DefWindowProc( hWnd, message, wParam, lParam );
}

BOOL InitDDraw( HWND hwnd )
{
DDSURFACEDESC ddsd; // Surface description structure.
DDPIXELFORMAT ddpf; // Surface format structure.

// Create the DirectDraw object.
if ( FAILED( DirectDrawCreate( NULL, &lpDD, NULL ) ) )
{
return Fail( hwnd, "Couldn't create DirectDraw object.\n" );
}

// Set normal cooperative level.
if ( FAILED( lpDD->SetCooperativeLevel( hwnd, DDSCL_NORMAL ) ) )
{
return Fail( hwnd, "Couldn't set cooperative level.\n" );
}

// Create the primary surface.
ddsd.dwSize = sizeof( ddsd );
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;

if ( FAILED( lpDD->CreateSurface( &ddsd, &lpDDSPrimary, NULL ) ) )
{
return Fail( hwnd, "Couldn't create primary surface.\n" );
}

// Create a clipper and attach it to the primary surface.
if ( FAILED( lpDD->CreateClipper( 0, &lpDDClipper, NULL ) ) )
{
return Fail( hwnd, "Couldn't create the clipper.\n" );
}

// Associate our clipper with our hwnd so it will be updated
// by Windows.
if ( FAILED( lpDDClipper->SetHWnd( 0, hwnd ) ) )
{
return Fail( hwnd, "Couldn't set the hwnd.\n" );
}

// Associate our clipper with the primary surface, so Blt
// will use it. If this step is skipped by defining NOCLIPPER, you
// can observe the effects of rendering without clipping. Other
// windows partially obscuring Inawin's will be overwritten.
#ifndef NOCLIPPER

if ( FAILED( lpDDSPrimary->SetClipper( lpDDClipper ) ) )
{
return Fail( hwnd, "Couldn't set the clipper.\n" );
}

#endif

lpDDClipper->Release();

// Check the surface format.
ddpf.dwSize = sizeof( ddpf );
if ( FAILED( lpDDSPrimary->GetPixelFormat( &ddpf ) ) )
{
return Fail( hwnd, "Couldn't get pixel format.\n" );
}

if ( ddpf.dwFlags & DDPF_PALETTEINDEXED8 )
{
// We are palettized, so create a palette and attach it to
// the primary surface.
lpDDPalette = DDLoadPalette( lpDD, "donut.bmp" );

if ( FAILED( lpDDSPrimary->SetPalette( lpDDPalette ) ) )
{
return Fail( hwnd, "Couldnt' get and/or set the palette.\n" );
}
}

//Insert GetDC test code here - this code is not part of the
// original Inawin program
HDC hdc;
// The call to GetDC crashes here!!
if ( FAILED( lpDDSPrimary -> GetDC(&hdc) )) {
return FALSE;
}
// This call is never reached since the program crashes in the call
above
lpDDSPrimary->ReleaseDC( hdc );



// Create a surface and load our "sprite" into it.
lpDDSDonut = DDLoadBitmap( lpDD, "donut.bmp", 0, 0 );

if ( lpDDSDonut == NULL )
{
return Fail( hwnd, "Could load the donut.\n" );
}

return TRUE;
}

BOOL RestoreAll( void )
{
HRESULT ddrval;

// Try restoring the primary first
ddrval = lpDDSPrimary->Restore();

if ( ddrval == DDERR_WRONGMODE )
{
// The restore failed because the display mode was
// changed. Destroy everything then re-create it.
OutputDebugString( "Display mode changed!\n" );
ReleaseObjects();
return InitDDraw( hWndMain );
}
else if ( FAILED( ddrval ) )
{
// We failed for some other reason.
OutputDebugString( "Random restore failure.\n" );
return FALSE;
}
else
{
// We're OK. Restore everything else.
if ( FAILED( lpDDSDonut->Restore() ) ) return FALSE;
if ( FAILED( DDReLoadBitmap( lpDDSDonut, "donut.bmp" ) ) )
return FALSE;
}
return TRUE;
}

BOOL doInit( HINSTANCE hInstance, int nCmdShow )
{
HWND hwnd;
WNDCLASS wc;
RECT rc1;

// Set up and register window class.
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon( hInstance, IDI_APPLICATION );
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.hbrBackground = NULL;
wc.lpszMenuName = NAME;
wc.lpszClassName = NAME;
RegisterClass( &wc );

// Create a window.
hwnd = CreateWindowEx(
0,
NAME,
TITLE,
WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX,
CW_USEDEFAULT,
SW_SHOW,
0,
0,
NULL,
NULL,
hInstance,
NULL );

if ( !hwnd )
{
return FALSE;
}

hWndMain = hwnd; // Save the window handle.

// Set the desired size for the client area of the window.
// The sprite is only 64x64, so the HEL will stretch it.
SetRect( &rc1, 0, 0, 128, 128 );

// Adjust that to a size that includes the border, etc.
AdjustWindowRectEx( &rc1,
GetWindowStyle( hwnd ), // Style of our main window.
GetMenu( hwnd ) != NULL, // Does the window have a menu?
GetWindowExStyle( hwnd ) ); // Extended style of the main window.

// Adjust the window to the new size.
MoveWindow( hwnd,
CW_USEDEFAULT,
CW_USEDEFAULT,
rc1.right - rc1.left,
rc1.bottom - rc1.top,
FALSE );

// Create all our DirectDraw objects.
if ( !InitDDraw( hwnd ) ) return FALSE;

ShowWindow( hwnd, nCmdShow );

return TRUE;
}

BOOL UpdateFrame( HWND hwnd )
{
RECT rcFrame;
DWORD dwTickCount;

// Check to see if it's time to update the frame.
dwTickCount = GetTickCount();
if ( ( dwTickCount - dwLastTickCount ) <= DELAY )
{
return TRUE;
}
dwLastTickCount = dwTickCount;

// Update the sprite image with the current frame.
rcFrame.top = ( ( dwFrame / 5 ) * 64 );
rcFrame.left = ( ( dwFrame % 5 ) * 64 );
rcFrame.bottom = rcFrame.top + 64;
rcFrame.right = rcFrame.left + 64;

// If the user has changed the display resolution our
// surfaces could be lost.
if ( FAILED( lpDDSPrimary->IsLost() ) )
{
if ( !RestoreAll() )
{
return Fail( hwnd, "Couldn't restore surfaces.\n" );
}
}

// Update the window with the new sprite frame. Notice that the
// destination rectangle is our client rectangle, not the
// entire primary surface.
if ( FAILED( lpDDSPrimary->Blt( &rcWindow, lpDDSDonut, &rcFrame,
DDBLT_WAIT, NULL ) ) )
{
return Fail( hwnd, "Couldn't Blt sprite.\n" );
}

// Advance the frame for next time.
dwFrame++;
if ( dwFrame > 29 ) dwFrame = 0;

return TRUE;
}

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;

if ( !doInit( hInstance, nCmdShow ) )
{
return FALSE;
}

while ( 1 )
{
if ( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )
{
if ( !GetMessage( &msg, NULL, 0, 0 ) )
{
return msg.wParam;
}
TranslateMessage( &msg );
DispatchMessage( &msg );
}
else if ( bActive )
{
UpdateFrame( hWndMain );
}
else
{
WaitMessage();
}
}
}


EuroDog

unread,
Dec 9, 1998, 3:00:00 AM12/9/98
to

Ricky Ip wrote in message <74lcoa$998$1...@pulp.ucs.ualberta.ca>...

>Hi. I am have some nasty problems with GetDC with a DirectDraw surface.
>When I make a GetDC call, not only does it crash the program, but all of
>Windows 95 locks up and I am forced to reboot. I am attempting to get the
>device context of my back buffer but when I make the GetDC call, I don't
>even get a return value but instead, Windows 95 crashes on me. I never
>lock or unlock my surfaces so there should be no conflict when GetDC locks
>my surface.
>


Are you using the debugger to trace over GetDC()? Every time I trace this,
it kills both my remote machine and the IDE, even though I can run it or run
past it at full speed with no problems.
Does anyone else have similar probs, or have a solution to this?

EuroDog

unread,
Dec 9, 1998, 3:00:00 AM12/9/98
to

Ricky Ip wrote in message <74lcoa$998$1...@pulp.ucs.ualberta.ca>...
>Hi. I am have some nasty problems with GetDC with a DirectDraw surface.
>When I make a GetDC call, not only does it crash the program, but all of
>Windows 95 locks up and I am forced to reboot. I am attempting to get the
>device context of my back buffer but when I make the GetDC call, I don't
>even get a return value but instead, Windows 95 crashes on me. I never
>lock or unlock my surfaces so there should be no conflict when GetDC locks
>my surface.

I've looked at both programs, and I can't see any 'back buffer' being
created, or any attempted GetDC on it. What you seem to have is a primary
surface in a Window, upon which a sprite, which is represented as a surface,
is blitted.


>
>To simplify my problem for anybody that would like to help, I've tried
>getting the device context of the primary surface in the "Inawin" program
>from the sdk that came with the book "Inside DirectX." The "Inawin"
>program came with the DirectX sdk, in the directory "code\chap12\inawin".
>Ironically, when I try to get a device context for the primary surface in
>"Inawin," it also crashes Windows 95 on me. A snippet of the "Inawin"
>code with the GetDC code that I added is below:

'Inside DirectX' deals with DX5 (well, my copy does), are you using DX6 sdk?
The tutorials given with DX6 use the newest DirectDraw interface (v4).

*straws clutched*
I can't see much wrong with your program, except maybe you could try a
lpDDSPrimary->Restore() before GetDC().

Hakon Steinø

unread,
Dec 9, 1998, 3:00:00 AM12/9/98
to

Matthew Hotstone wrote:
>
> EuroDog wrote in message
> <9053104ECD0CD211AF4...@probe-2.Acclaim-Euro.net>...


> >Are you using the debugger to trace over GetDC()? Every time I trace this,
> >it kills both my remote machine and the IDE, even though I can run it or
> run
> >past it at full speed with no problems.
> >Does anyone else have similar probs, or have a solution to this?
>

> Internally GetDC locks the surface (I believe) creating a Win16 lock (or
> Mutex or whatever the other term for it is). Basically, in a Win16 Lock no
> other programmes can run - that includes debuggers etc. So your programme
> is halted until the debugger gets it going again, but the debugger can't run
> 'cause your programme has caused this Win16 Lock... The only solution is
> to NEVER try to "step" through any code between a GetDC and a ReleaseDC, or
> a Lock and an Unlock..
>
> -Matt

True! Always, *always* ReleaseDC() before anything else. But... if you
specify NOSYSLOCK and (...i forgot the name, but it allocates system
memory only) when creating your surfaces, there is no lock! you can step
through all the code you want.

You can also specify NOSYSLOCK in the DirectX control panel.

- Hakon

Ricky Ip

unread,
Dec 9, 1998, 3:00:00 AM12/9/98
to
In rec.games.programmer EuroDog <euro...@hotmail.com> wrote:

> Ricky Ip wrote in message <74lcoa$998$1...@pulp.ucs.ualberta.ca>...

> I've looked at both programs, and I can't see any 'back buffer' being


> created, or any attempted GetDC on it. What you seem to have is a primary
> surface in a Window, upon which a sprite, which is represented as a surface,
> is blitted.

I think I figured out what the problem was. As an earlier poster
suggested, you can't run the debugger and GetDC at the same time.
Anyways, I tried running my program without the debugger and it worked (it
works when I just run it from the DOS command prompt). I was actually
running my program from the "Execute" command under the "Build" menu in
Visual C++ 4.0. For some reason, GetDC doesn't cooperate very well with
the "Execute" command. I should probably disable the debugger if I run my
program from Visual C++.

Still, this is a big drawback. I was hoping to display text on a
DirectDraw surface using the Windows GDI text functions. Unfortunately,
this requires a GetDC on the surface before calling the GDI text
functions. Unless there is another way to get GetDC to work smoothly with
the debugger, I guess I'll have to find another way to display text :(

> 'Inside DirectX' deals with DX5 (well, my copy does), are you using DX6 sdk?
> The tutorials given with DX6 use the newest DirectDraw interface (v4).

Nope. I'm still using DX5 (actually, I think the version with "Inside
DirectX" is DX 5.2). All I am doing is running "Inawin" from the Visual
C++ 4.0, through "Execute" under the "Build" menu.


Thanks for the help everybody :)

--
Ricky.


= == === ==== ===== ====== ====== ======= ====== ====== ===== ==== === == =
"Hence to fight and conquer in all your battles is not supreme excellence;
supreme excellence consists in breaking the enemy's resistance without
fighting."
- The Art of War
= == === ==== ===== ====== ====== ======= ====== ====== ===== ==== === == =


Jonathan Hays

unread,
Dec 9, 1998, 3:00:00 AM12/9/98
to
You can still use the GDI text functions. You just can't step through
it in the debugger. The problem isn't GDI, the problem is
multi-threading. When you call GetDC() it uses a WIN16 lock, which
serializes access to GDI and USER which your debugger will try and use,
but it can't, and your ddraw program won't continue until it hears from
the debugger. So now you have the debugger waiting on the program, and
the program waiting on the debugger, and you're essentially in
deadlock. If you don't set a breakpoint between GetDC and ReleaseDC
function calls your program should run fine. So, you actually can use
GDI to do text. Just don't watch! = )

-Jonathan
--
************************************
"Its a dog eat dog world, and
I'm wearing milk bone underwear"
-Norm Peterson
************************************

---------------------------
Jonathan Hays
Senior Software Engineer
Mudpuppy Studios Inc.
jh...@mudpup.com
---------------------------

Matthew Hotstone

unread,
Dec 10, 1998, 3:00:00 AM12/10/98
to

Ron Fosner

unread,
Dec 12, 1998, 3:00:00 AM12/12/98
to
If you use a windowed mode instead of fullscreen/exclusive, you should be
able to debug fine.

Ron

0 new messages