Jump to content
  • Advertisement
Sign in to follow this  
BrianMJC

D3D Cursor Help Request

This topic is 4579 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi all, I've been having trouble getting my D3D cursor to appear onscreen. I have confirmed that everything seems to be working correctly: the mouse device is receiving valid input and correctly updating the cursor's screen coordinates, the surface is correctly loaded from file, the surface meets the correct cursor restrictions (A8R8G8B8, 32x32, default memory pool), my video adapter does fully support hardware cursors (D3DCURSORCAPS_COLOR is true), and I do turn the Windows cursor off and my D3D cursor on correctly. When I run it in debug mode (in MSVC++ .NET 2003, WinXP Pro platform w/ SP2), I receive no exceptions, but I have been getting a D3D helper failure message and a warning since I wrote the D3D startup code a while back:
Quote:
Direct3D9: (INFO) :Failed to create driver indexbuffer D3D9 Helper: Warning: Default value for D3DRS_POINTSIZE_MAX is 2.19902e+012f, not 1.44115e+017f. This is ok.
Up until now, there has been no visible evidence of a problem, however. I don;t understand exactly what these errors mean, so I put them here in case they have any bearing on the problem (and possible future problems). The game goes into fullscreen mode, correctly displays a background surface, but displays no cursor. In windowed mode, I just have it use the Windows cursor. Having no access to the debugger while running in fullscreen mode has not helped me figure this problem out. :/ Here's my code:
// cursor.cpp

void ccursor::load (const string csFilename, point &ptHot)
	{
	// Retain params for device reset.
	_sFilename = csFilename;
	_xHot = ptHot.x;
	_yHot = ptHot.y;
	// The next several steps are mimiced in ccursor::restore().
	restore ();
	// Initialize remaining parameters.
	_rEdge.right = pgfx->videoWidth () - 1;
	_rEdge.bottom = pgfx->videoHeight () - 1;
	_rEdge.left = 0;
	_rEdge.top = 0;
	_rEdgeO.right = _rEdge.right - _xHot;
	_rEdgeO.bottom = _rEdge.bottom - _yHot;
	_rEdgeO.left = -(int)_xHot;
	_rEdgeO.top = -(int)_yHot;
	_xo = pgfx->videoWidth () / 2;
	_yo = pgfx->videoHeight () / 2;
	_x = _xHot + _xo;
	_y = _yHot + _yo;
	_xp = _x;
	_yp = _y;
	_xRight = (pgfx->videoWidth () * 3) / 4;
	_yDown = (pgfx->videoHeight () * 3) / 4;
	_xLeft = pgfx->videoWidth () / 4;
	_yUp = pgfx->videoWidth () / 4;
	// Set initial cursor position.
	_pd3dDev->SetCursorPosition (_xo, _yo, D3DCURSOR_IMMEDIATE_UPDATE);
	}

void ccursor::restore ()
	{
	// Begin with a clean slate.
	if (_pd3dSurface)
		{
		_pd3dSurface->Release ();
		_pd3dSurface = 0;
		}
	// Create surface.
	_hr = _pd3dDev->CreateOffscreenPlainSurface (32, 32, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &_pd3dSurface, 0);
	if (FAILED (_hr))
		{
		str = "ccursor::restore() -- Failed to create image surface: " + error ();
		throw str;
		}
	// Load file into surface.
	_hr = D3DXLoadSurfaceFromFile (_pd3dSurface, 0, 0, _sFilename.c_str (), 0, D3DX_FILTER_NONE, _cdwcBlack, 0);
	if (FAILED (_hr))
		{
		str = "ccursor::restore() -- Failed to load file \"" + _sFilename + "\" into image surface: " + error ();
		throw str;
		}
		// Setup cursor properties.
	_hr = _pd3dDev->SetCursorProperties (_xHot, _yHot, _pd3dSurface);
	if (FAILED (_hr))
		{
		str = "ccursor::restore() -- Failed to set cursor properties: " + error ();
		throw str;
		}
	// Show the cursor
	_pd3dDev->ShowCursor (true);
	}

// cursor.h

inline void ccursor::redraw ()

	{

	// Only redraw if using DI (else let the OS handle cursors).
	if (pgfx->fullscreenMode ())

		{

		// Update to new position and remember the previous one.
		_xp = _x;
		_yp = _y;
		_x += _diMouseState.lX;
		_y += _diMouseState.lY;
		_xo += _diMouseState.lX;
		_yo += _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.
		_pd3dDev->SetCursorPosition (_x, _y, D3DCURSOR_IMMEDIATE_UPDATE);

		}

	}

// input.cpp


void cinput::get ()

	{

	static void *pvr;

	_bGetInput = true;

	// Remember previous keyboard and mouse data.
	pvr = memcpy ((void *)_diPrevKeyS, (void *)_diKeyState, 256);
	if (!pvr)
		{
		str = "cinput::get() -- Failed to record previous keyboard state";
		throw str;
		}
	pvr = memcpy ((void *)&_diPrevMouseS, (void *)&_diMouseState, sizeof (DIMOUSESTATE));
	if (!pvr)
		{
		str = "cinput::get() -- Failed to record previous mouse state";
		throw str;
		}

	// Get new keyboard data.
	_hr = _pdiKeyboard->GetDeviceState (sizeof (DIKEYSTATE), (LPVOID)_diKeyState);
	if (FAILED (_hr))
		{
		str = "cinput::get() -- Failed to get keyboard input: " + error ();
		throw str;
		}

	// Get new mouse data.
	if (pgfx->fullscreenMode ())
		{
		_hr = _pdiMouse->GetDeviceState (sizeof (DIMOUSESTATE), (LPVOID)&_diMouseState);
		if (FAILED (_hr))
			{
			str = "cinput::get() -- Failed to get mouse input: " + error ();
			throw str;
			}
		}
	else
		{
		static point pt;
		GetCursorPosOS (pt);
		pcur->_x = pt.x;
		pcur->_y = pt.y;
		if (pcur->_bLMBDown)
			{
			_diMouseState.rgbButtons[0] = 0x80;
			}
		else
			{
			_diMouseState.rgbButtons[0] = 0x00;
			}
		if (pcur->_bRMBDown)
			{
			_diMouseState.rgbButtons[1] = 0x80;
			}
		else
			{
			_diMouseState.rgbButtons[1] = 0x00;
			}
		}

	}

// state.cpp

void cmainstate::run ()
	{
	pinput->get ();
	pgfx->beginScene ();
	psurBack->displayFull ();
	pcur->redraw ();
	pgfx->endScene ();
	}


Notes: pinput: ptr to input class. pgfx: ptr to graphics class. psur: ptr to surface class. pcur: ptr to cursor class. pinput->get(): retrieves current keyboard and mouse device states. pgfx->beginScene(): clears screen and invokes IDirect3D9Device::BeginScene(). pgfx->endScene(): invokes IDirect3D9Device::EndScene() and IDirect3D9Device::PresentParams(). Thanks for any help! :)

Share this post


Link to post
Share on other sites
Advertisement
If it helps, I noticed the Windows cursor appears on the top of the screen if I move the mouse up in fullscreen mode (e.g. when my D3D cursor should appear instead), but it disappears when I move it down again (e.g. neither cursor is visible). But ShowCursor() is definitely set to false and IDirect3D9Device::ShowCursor() to true! Thanks.

Share this post


Link to post
Share on other sites
Couple things I like to make sure on:

Are you passing FALSE or NULL to ::SetCursor()? You should be passing NULL.
You should also pass TRUE instead of true to functions that take BOOLs. It probably doesn't matter though.

You might also try trapping the WM_SETCURSOR message, and returning TRUE to prevent Windows from resetting the cursor. (And better yet, setting the cursor there too.) Just good practice, and it might help.

Share this post


Link to post
Share on other sites
Hi RenderTarget,

NULL, FALSE, false, 0, they all work the same.

I was aware that it is standard procedure to do the ShowCursor() stuff when a WM_SETCURSOR message is processed. I've never had a problem not doing so before, however (I've been coding DX and DI since 6.1).

In fact, I don't see how it's even possible to do so. A WM_SETCURSOR message is generated automatically whenever CreateWindow() is called. And D3D requires a valid HWND to the app window before it can be setup. So, to call IDirect3D9Device::ShowCursor() during a WM_SETCURSOR message is to do so once CreateWindow() is called and therefore before D3D is initialized, no doubt resulting in an exception (you need D3D initialized before you can create the cursor's surface). Am I missing something here?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!