Skip to main content
gamedev.net
🔒 Locked 🎮 Unity

Direct Input - Buffered Keyboard

Started by brekehan Aug 9, 2007 at 12:51 AM 1 replies 2.5k views
Original Post
brekehan
brekehan
I don't want to work with immediate data. I want to be able to deal with lag and therefore want buffred input. The SDK sucks on explaining how to work with buffered input, as all thier examples and explanations work with immediate. Anyway, my question is: What messages will you get when the key is held down? I was under impression that my following code:

// We have obtained keyboard data
Event * event = new Event(EVENT_DIKEYBOARD);
event->m_data.diKeyboardEventData.key		= data.dwOfs;
event->m_data.diKeyboardEventData.pressed	= 0 != (data.dwData & 0x00000080);
event->m_data.diKeyboardEventData.time		= data.dwTimeStamp;
PostEvent(event);
Would produce an sequence of pressed, pressed, presssed, (and then when released) !pressed However, My application only seems to be getting one pressed event. Here is some of my code for review:

void EventManager::GetDIKeyboardData()
{
	DIDEVICEOBJECTDATA	data;					// Buffer to hold a Direct Input event
	DWORD				numElements =  1;		// Number of elements in the buffer
	HRESULT				result		=  1;		// Result from an attempt at getting the buffered data from Direct Input

	// Make sure the keyboard was set to be used with Direct Input
	if(m_dikeyboard)
	{
		// While an element remains to be retrieved
		while(numElements)
		{
			// Get the buffered data
			result = m_dikeyboard->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), &data, &numElements, 0);
			
			// Check if the keyboard needs to be aquired
			if(result == DIERR_NOTACQUIRED || result == DIERR_INPUTLOST)
			{
				// If the keyboard is not aquired than attempt to aquire it
				// Don't worry about not being successful, we will try again next update
				// Aquire the keyboard
				if(m_dikeyboard)
					m_dikeyboard->Acquire();

				break;
			}

			// Was data retrieved? 
			else if(SUCCEEDED(result) && numElements == 1)
			{
				// Was there overflow?
				if(result == DI_BUFFEROVERFLOW)
				{ 
					// Buffer has overflowed
				}

				// We have obtained keyboard data
				Event * event = new Event(EVENT_DIKEYBOARD);
				event->m_data.diKeyboardEventData.key		= data.dwOfs;
				event->m_data.diKeyboardEventData.pressed	= 0 != (data.dwData & 0x00000080);
				event->m_data.diKeyboardEventData.time		= data.dwTimeStamp;
				PostEvent(event);
			}

			// Otherwise, was there an unhandled an error?
			else if(FAILED(result))
			{
				throw Error("Failed to get buffered keyboard data from DirectInput", "void EventManager::GetDIKeyboardData()", "EventManager.cpp");
			}
		}
	}
}

unsigned EventManager::PostEvent(Event * event)
{
	m_eventQueue.push(event);
	
	return static_cast<unsigned>(m_eventQueue.size());
}

void EventManager::Update()
{
	// Get messages from Direct Input, if it is being used
	if(m_dxinput)
	{
		GetDIKeyboardData();	
	}

	// Have every registered event handler process thier events
	while(!m_eventQueue.empty())
	{
		Event * event = m_eventQueue.front();
		m_eventQueue.pop();

		EventHandlerVector::iterator it;
		for(it = m_eventHandlerVectors[event->m_type].begin(); it != m_eventHandlerVectors[event->m_type].end(); it++)
		{
			(*it)->ProcessEvent(event);
		}

		delete event;
	}
}

int EventTester::ProcessEvent(Event * event)
{
	switch(event->m_type)
	{
	case EVENT_DIKEYBOARD:
		if(event->m_data.diKeyboardEventData.pressed)
		{
			switch(event->m_data.diKeyboardEventData.key)
			{
			case DIK_UP:
				break;

			case DIK_DOWN:
				break;

			case DIK_LEFT:
				m_camera->Pitch( 1.0f * D3DX_PI );
				break;

			case DIK_RIGHT:
				m_camera->Pitch( GetTimeDelta() * 2 * D3DX_PI );
				break;

			default:
				break;
			}
		}
		break;
		
	case LBUTTON_DBLCLK:
		MessageBox(NULL, "Left button - double click", "Event", MB_OK);
		break;

	case LBUTTON_DOWN:
		MessageBox(NULL, "Left click", "Event", MB_OK);
		break;

	case RBUTTON_DBLCLK:
		MessageBox(NULL, "Right button - double click", "Event", MB_OK);
		break;

	case RBUTTON_DOWN:
		MessageBox(NULL, "Right click", "Event", MB_OK);
		break;
	
	default:
		break;
	}

	return 0;
}
Evil Steve
Evil Steve
Quote:
Original post by brekehan
Anyway, my question is:
What messages will you get when the key is held down?
WM_KEYDOWN! You should never, ever, ever use DirectInput for keyboard or mouse input. It's like using BIOS interupts to do keyboard input, except slower.

  • Window messages are faster (DirectInput just creates another thread to read window messages)
  • Window messages give you things like key repeat for free, DirectInput doesn't (Which I think is the problem you're seeing)
  • Window messages handle shifted letters and caps/num/scroll lock properly, DirectInput doesn't
  • Window message obey the users control pannel settings, DirectInput does not
  • Window messages are "free". They get sent to your window without you having to write pages and pages of code to initialise a DirectInput device
  • Microsoft recommend that you do not use DierctInput for keyboard or mouse input:
    Quote:
    Overall, using DirectInput offers no advantages when reading data from mouse or keyboard devices, and the use of DirectInput in these scenarios is discouraged.



    So the solution is: Don't use DirectInput [smile]
  • brekehan
    brekehan
    hmm, didnt realize. I was always under the impression that dinput was faster.

    Topic Locked

    This topic has been locked by a moderator. New replies are not allowed.

    Sign in to reply to this topic.