Direct Input 8

Set up the Timer Message Map and Methods

Step 1: Create a Message Map for the WM_TIMER event for the CDirectInput1View class

void CDirectInput1View::OnTimer(UINT nIDEvent)
{
   /*
   The Timer event looks to determine if the user wants to poll
   keyboard events in immediate or buffer mode.
   */

   UpdateData(TRUE);
   BOOL bImmediate = ( m_immediate_control.GetCheck() == BST_CHECKED );

   if( bImmediate )
   {
       if( FAILED( ReadImmediateData( AfxGetMainWnd()->m_hWnd ) ) )
       {
           KillTimer( 0 );    
           MessageBox(  _T("Error reading input state. ")
                             _T("The sample will now exit."),
                             _T("Keyboard"), MB_ICONERROR | MB_OK );
           EndDialog( m_hWnd, TRUE );
       }
   }
   else
   {
       if( FAILED( ReadBufferedData( AfxGetMainWnd()->m_hWnd ) ) )
       {
           KillTimer( 0 );    
           MessageBox( _T("Error reading input state. ")
                             _T("The sample will now exit."),
                             _T("Keyboard"), MB_ICONERROR | MB_OK );
           EndDialog( m_hWnd, TRUE );
       }
   }

   CFormView::OnTimer(nIDEvent);
}

Step 2: Insert into directInput1View.h:

HRESULT ReadImmediateData( HWND hDlg );
HRESULT ReadBufferedData( HWND hDlg );


Step 3: Source Code Insert directInput1View.cpp

HRESULT CDirectInput1View::ReadImmediateData( HWND hDlg )
{
   HRESULT hr;
   TCHAR   strNewText[256*5 + 1] = TEXT("");
   TCHAR   strElement[10];    
   BYTE    diks[256];   // DirectInput keyboard state buffer
   int     i;

   if( NULL == g_pKeyboard )
       return S_OK;
   
   // Get the input's device state, and put the state in dims
   ZeroMemory( &diks, sizeof(diks) );
   hr = g_pKeyboard->GetDeviceState( sizeof(diks), &diks );
   if( FAILED(hr) )
   {
       // DirectInput may be telling us that the input stream has been
       // interrupted.  We aren't tracking any state between polls, so
       // we don't have any special reset that needs to be done.
       // We just re-acquire and try again.

       
       // If input is lost then acquire and keep trying
       hr = g_pKeyboard->Acquire();
       while( hr == DIERR_INPUTLOST )
           hr = g_pKeyboard->Acquire();

       // Update the dialog text
       if( hr == DIERR_OTHERAPPHASPRIO || hr == DIERR_NOTACQUIRED )
       {
           m_data="Unacquired";
           UpdateData(FALSE);
       }
       // hr may be DIERR_OTHERAPPHASPRIO or other errors.  This
       // may occur when the app is minimized or in the process of
       // switching, so just try again later
       return S_OK;
   }
   
   // Make a string of the index values of the keys that are down
   for( i = 0; i < 256; i++ )
   {
       if( diks[i] & 0x80 )
       {
           wsprintf( strElement, "0x%02x ", i );
           strcat( strNewText, strElement );
       }
   }

   // Get the old text in the text box
   TCHAR strOldText[128];
   UpdateData(TRUE);

   strcpy(strOldText,m_data.GetBufferSetLength(m_data.GetLength()));
   m_data.ReleaseBuffer();
   
   // If nothing changed then don't repaint - avoid flicker
   if( 0 != lstrcmp( strOldText, strNewText ) )
   {
       m_data=strNewText;
       UpdateData(FALSE);
   }
   
   return S_OK;
}

//-----------------------------------------------------------------------------
// Name: ReadBufferedData()
// Desc: Read the input device's state when in buffered mode and display it.
//-----------------------------------------------------------------------------
HRESULT CDirectInput1View::ReadBufferedData( HWND hDlg )
{
   TCHAR              strNewText[256*5 + 1] = TEXT("");
   TCHAR              strLetter[10];    
   DIDEVICEOBJECTDATA didod[ SAMPLE_BUFFER_SIZE ];  // Receives buffered data
   DWORD              dwElements;
   DWORD              i;
   HRESULT            hr;

   if( NULL == g_pKeyboard )
       return S_OK;
   
   dwElements = SAMPLE_BUFFER_SIZE;
   hr = g_pKeyboard->GetDeviceData( sizeof(DIDEVICEOBJECTDATA),
                                    didod, &dwElements, 0 );
   if( hr != DI_OK )
   {
       // We got an error or we got DI_BUFFEROVERFLOW.
       //
       // Either way, it means that continuous contact with the
       // device has been lost, either due to an external
       // interruption, or because the buffer overflowed
       // and some events were lost.
       //
       // Consequently, if a button was pressed at the time
       // the buffer overflowed or the connection was broken,
       // the corresponding "up" message might have been lost.
       //
       // But since our simple sample doesn't actually have
       // any state associated with button up or down events,
       // there is no state to reset.  (In a real game, ignoring
       // the buffer overflow would result in the game thinking
       // a key was held down when in fact it isn't; it's just
       // that the "up" event got lost because the buffer
       // overflowed.)
       //
       // If we want to be cleverer, we could do a
       // GetDeviceState() and compare the current state
       // against the state we think the device is in,
       // and process all the states that are currently
       // different from our private state.
       hr = g_pKeyboard->Acquire();
       while( hr == DIERR_INPUTLOST )
           hr = g_pKeyboard->Acquire();

       // Update the dialog text
       if( hr == DIERR_OTHERAPPHASPRIO ||
           hr == DIERR_NOTACQUIRED )
       {
           m_data="Unacquired";
           UpdateData(FALSE);
       }

       // hr may be DIERR_OTHERAPPHASPRIO or other errors.  This
       // may occur when the app is minimized or in the process of
       // switching, so just try again later
       return S_OK;
   }

   if( FAILED(hr) )  
       return hr;

   // Study each of the buffer elements and process them.
   //
   // Since we really don't do anything, our "processing"
   // consists merely of squirting the name into our
   // local buffer.
   for( i = 0; i < dwElements; i++ )
   {
       // this will display then scan code of the key
       // plus a 'D' - meaning the key was pressed
       //   or a 'U' - meaning the key was released
       wsprintf( strLetter, "0x%02x%s ", didod[ i ].dwOfs,
                                        (didod[ i ].dwData & 0x80) ? "D" : "U");
       strcat( strNewText, strLetter );
   }

   // Get the old text in the text box
   TCHAR strOldText[128];
   UpdateData(TRUE);

   strcpy(strOldText,m_data.GetBufferSetLength(m_data.GetLength()));
   m_data.ReleaseBuffer();

   //strcpy(strOldText,m_data);

   // If nothing changed then don't repaint - avoid flicker
   if( 0 != lstrcmp( strOldText, strNewText ) )
   {
       m_data=strNewText;
       UpdateData(FALSE);
   }

   return S_OK;
}

You might also like...

Comments

About the author

David Nishimoto United States

NishiSoft provides Part I of the Information Technology Project collaboration. Sign up and list your IT project tasks, assign task too friends, and get percent complete task.

Part will ...

Interested in writing for us? Find out more.

Contribute

Why not write for us? Or you could submit an event or a user group in your area. Alternatively just tell us what you think!

Our tools

We've got automatic conversion tools to convert C# to VB.NET, VB.NET to C#. Also you can compress javascript and compress css and generate sql connection strings.

“I invented the term Object-Oriented, and I can tell you I did not have C++ in mind.” - Alan Kay