Archived

This topic is now archived and is closed to further replies.

BrianMJC

Disappearing D3D Cursor Problem

Recommended Posts

Hi all, I am in the process of updating my isometric engine from DirectDraw 6 to Direct3D 8 and was hoping someone could help me figure out how to regain my cursor''s D3D image surface upon regaining application focus. Basically, all works fine in fullscreen mode until I hit ALT-TAB. When I hit it again to return to my program, the graphics reset correctly (a background image surface is displayed properly) but my cursor does not reappear. I tried reacquiring my input devices, to no avail. I also tried calling the IDirect3DDevice8::ShowCursor method, to no avail. I see nothing in the documentation to help me out any further, and I''m out of guesses. Here''s my code:


// C L E A R   S C R E E N //////////////////////////////////////////////////

//

// Clear the screen (fullscreen mode) or window (windowed mode).

//

// return value - success or failure

//

inline estate ClearScreen ()

    {

    // Clear the screen.

    hr = g_pd3dDev->Clear (0, NULL, D3DCLEAR_TARGET, g_cd3dColorBlack, 0.0f, 0);
    if (FAILED (hr))
        {
        sReport = "ClearScreen -- Failed to clear screen: ";
        sReport += D3DError (hr);
        Log (sReport);
        return g_ceSError;
        }
    return g_eState;
    
    }


// O P E N   S C E N E //////////////////////////////////////////////////////

//

// Opens the viewport in order to begin rendering.

//

// return value - success or failure

//

inline estate OpenScene ()

    {

    // Clear the viewport.

    sr = ClearScreen ();
    if (!sr)
        {
        Log ("OpenScene -- Failed to clear the screen.");
        return g_ceSError;
        }
    
    // Begin the scene.

    g_pd3dDev->BeginScene ();

    return g_eState;

    }


// R E N D E R   S C E N E ///////////////////////////////////////////////////

//

// Renders the scene to the viewport.

//

// return value - continue or pause if focus lost.

//

inline estate RenderScene ()

    {

    // End the scene.

    g_pd3dDev->EndScene ();
    
    // Present the scene.

    hr = g_pd3dDev->Present (NULL, NULL, NULL, NULL);
    if (D3DERR_DEVICELOST == hr)
        if (g_bFocus)
            {
            Log ("RenderView -- Lost device, switching to windowed mode.");
            g_bFocus = false;
            g_ePrevState = g_eState;
            return g_ceSPause;
            }

    return g_eState;
            
    }


// T E S T   F O C U S ///////////////////////////////////////////////////////

//

// Tests to see if we have regained focus so we know when to reset graphics.

//

// return value - ready or not

//

bool TestFocus ()

    {

    hr = g_pd3dDev->TestCooperativeLevel ();
    if (D3DERR_DEVICENOTRESET == hr)
        {
        Log ("TestFocus -- Device available for reset, switching back to fullscreen.");
        return true;
        }
    return false;

    }


// G R A P H I C S   R E S E T ///////////////////////////////////////////////

//

// Reset the graphics.

//

// return value - success or failure

//

estate GraphicsReset ()

    {
    
    // Grab display mode.

    g_pd3d->EnumAdapterModes (D3DADAPTER_DEFAULT, g_uMode, &g_d3dDisplayMode);

    // Fill in back buffer information relevant to fullscreen mode...

    // Screen width and height..

    g_d3dParams.BackBufferWidth = g_d3dDisplayMode.Width;
    g_d3dParams.BackBufferHeight = g_d3dDisplayMode.Height;
    
    // Not windowed mode, use desired refresh rate.

    g_d3dParams.Windowed = false;
    g_d3dParams.FullScreen_RefreshRateInHz = g_d3dDisplayMode.RefreshRate;

    // And voila, reset it.

    hr = g_pd3dDev->Reset (&g_d3dParams);
    if (FAILED (hr))
        {
        Log ("GraphicsReset -- Failed to reset graphics.");
        return g_ceSError;
        }

    g_bFocus = true;

    return g_ePrevState;

    }


// S E T   C U R S O R ///////////////////////////////////////////////////////

inline void csurface::SetCursor (uint xPos, uint yPos)

    {

    g_pd3dDev->SetCursorPosition (xPos, yPos, D3DCURSOR_IMMEDIATE_UPDATE);

    }


// G E T   I N P U T /////////////////////////////////////////////////////////

//

// Get the current input (if any) for the keyboard and mouse.

//

// return value - success or failure

//

estate GetInput ()

    {

    static void *pvr;

    // Remember previous keyboard data, so we can check for key presses and releases.

    pvr = memcpy ((void *)g_diPrevKeyS, (void *)g_diKeyState, 256);
    if (!pvr)
        {
        Log ("GetInput -- Failed to record previous keyboard state.");
        return g_ceSError;
        }

    // Get new keyboard state.

    hr = g_pdiKeyboard->GetDeviceState (sizeof (DIKEYSTATE), (LPVOID)g_diKeyState);
    if (FAILED (hr))
        {
        sReport = "GetInput -- Failed to get keyboard input: ";
        sReport += DIError (hr);
        Log (sReport);
        return g_ceSError;
        }

    // Get any mouse input.

    pvr = memcpy ((void *)&g_diPrevMouseS, (void *)&g_diMouseState, sizeof (DIMOUSESTATE));
    if (!pvr)
        {
        Log ("GetInput -- Failed to record previous mouse state.");
        return g_ceSError;
        }
    hr = g_pdiMouse->GetDeviceState (sizeof (DIMOUSESTATE), (LPVOID)&g_diMouseState);
    if (FAILED (hr))
        {
        sReport = "GetInput -- Failed to get mouse input: ";
        sReport += DIError (hr);
        Log (sReport);
        return g_ceSError;
        }

    return g_eState;

    }


// R E D R A W ///////////////////////////////////////////////

//

// Update cursor position and redraw it.

//

// return value - none.

//

void ccursor::Redraw ()

    {
    
    // Update to new position and remember the previous one.

    xp = x;
    yp = y;
    x += g_diMouseState.lX;
    y += g_diMouseState.lY;
    xo += g_diMouseState.lX;
    yo += g_diMouseState.lY;

    // Keep it within the screen''s bounds.

    if (x > rEdge.right)
        {
        x = rEdge.right;
        xo = rEdgeO.right;
        }
    if (y > rEdge.bottom)
        {
        y = rEdge.bottom;
        yo = rEdgeO.bottom;
        }
    if (x < rEdge.left)
        {
        x = rEdge.left;
        xo = rEdgeO.left;
        }
    if (y < rEdge.top)
        {
        y = rEdge.top;
        yo = rEdgeO.top;
        }

    // Redraw the cursor at new position.

    pSurface->SetCursor (x, y);

    }

Basically, I call GetInput first, then OpenScene, then draw a background image surface, then call RenderScene, and finally Redraw the cursor. Note that ''csurface'' and ''ccursor'' are custom classes I created to mask DirectX and make my code API independent (so I can port it to Linux and Mac eventually). Thanks very much!

Share this post


Link to post
Share on other sites