E:/Download/ois-1.0RC1/src/win32/Win32KeyBoard.cpp

Go to the documentation of this file.
00001 /*
00002 The zlib/libpng License
00003 
00004 Copyright (c) 2006 Phillip Castaneda (pjcast -- www.wreckedgames.com)
00005 
00006 This software is provided 'as-is', without any express or implied warranty. In no event will
00007 the authors be held liable for any damages arising from the use of this software.
00008 
00009 Permission is granted to anyone to use this software for any purpose, including commercial 
00010 applications, and to alter it and redistribute it freely, subject to the following
00011 restrictions:
00012 
00013     1. The origin of this software must not be misrepresented; you must not claim that 
00014                 you wrote the original software. If you use this software in a product, 
00015                 an acknowledgment in the product documentation would be appreciated but is 
00016                 not required.
00017 
00018     2. Altered source versions must be plainly marked as such, and must not be 
00019                 misrepresented as being the original software.
00020 
00021     3. This notice may not be removed or altered from any source distribution.
00022 */
00023 #include "Win32/Win32InputManager.h"
00024 #include "Win32/Win32KeyBoard.h"
00025 #include "OISException.h"
00026 #include "OISEvents.h"
00027 #include <sstream>
00028 
00029 using namespace OIS;
00030 
00031 //--------------------------------------------------------------------------------------------------//
00032 Win32Keyboard::Win32Keyboard( InputManager* creator, IDirectInput8* pDI, bool buffered, DWORD coopSettings )
00033 {
00034         mCreator = creator;
00035         mBuffered = buffered;
00036         mKeyboard = 0;
00037         mDirectInput = pDI;
00038         coopSetting = coopSettings;
00039         mType = OISKeyboard;
00040         listener = 0;
00041 
00042         //Clear our keyboard state buffer
00043         memset( &KeyBuffer, 0, 256 );
00044         deadKey = '\0';
00045 }
00046 
00047 //--------------------------------------------------------------------------------------------------//
00048 void Win32Keyboard::_initialize()
00049 {
00050         mModifiers = 0;
00051         deadKey = '\0';
00052 
00053         if(FAILED(mDirectInput->CreateDevice(GUID_SysKeyboard, &mKeyboard, NULL)))
00054                 OIS_EXCEPT( E_General, "Win32Keyboard::Win32Keyboard >> Could not init device!");
00055 
00056         if(FAILED(mKeyboard->SetDataFormat(&c_dfDIKeyboard)))
00057                 OIS_EXCEPT( E_General, "Win32Keyboard::Win32Keyboard >> format error!");
00058 
00059         HWND hwin = ((Win32InputManager*)mCreator)->getWindowHandle();
00060 
00061         if(FAILED(mKeyboard->SetCooperativeLevel( hwin, coopSetting)))
00062                 OIS_EXCEPT( E_General, "Win32Keyboard::Win32Keyboard >> coop error!");
00063 
00064         if( mBuffered )
00065         {
00066                 DIPROPDWORD dipdw;
00067                 dipdw.diph.dwSize       = sizeof(DIPROPDWORD);
00068                 dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
00069                 dipdw.diph.dwObj        = 0;
00070                 dipdw.diph.dwHow        = DIPH_DEVICE;
00071                 dipdw.dwData            = KEYBOARD_DX_BUFFERSIZE;
00072 
00073                 if (FAILED(mKeyboard->SetProperty( DIPROP_BUFFERSIZE, &dipdw.diph )))
00074                         OIS_EXCEPT( E_General, "Win32Keyboard::Win32Keyboard >> buffer error!");
00075         }
00076 
00077         HRESULT hr = mKeyboard->Acquire();
00078         if(FAILED(hr) && hr != DIERR_OTHERAPPHASPRIO)
00079                 OIS_EXCEPT( E_General, "Win32Keyboard::Win32Keyboard >> aquire error!");
00080 }
00081 
00082 //--------------------------------------------------------------------------------------------------//
00083 Win32Keyboard::~Win32Keyboard()
00084 {
00085         if(mKeyboard)
00086         {
00087                 mKeyboard->Unacquire();
00088                 mKeyboard->Release();
00089                 mKeyboard = 0;
00090         }
00091 }
00092 
00093 //--------------------------------------------------------------------------------------------------//
00094 void Win32Keyboard::capture()
00095 {
00096         if( mBuffered )
00097                 _readBuffered();
00098         else
00099                 _read();
00100 }
00101 
00102 //--------------------------------------------------------------------------------------------------//
00103 void Win32Keyboard::_readBuffered()
00104 {
00105         DIDEVICEOBJECTDATA diBuff[KEYBOARD_DX_BUFFERSIZE];
00106         DWORD entries = KEYBOARD_DX_BUFFERSIZE;
00107         HRESULT hr;
00108 
00109         hr = mKeyboard->GetDeviceData( sizeof(DIDEVICEOBJECTDATA), diBuff, &entries, 0 );
00110         if( hr != DI_OK )
00111         {
00112                 hr = mKeyboard->Acquire();
00113                 while( hr == DIERR_INPUTLOST )
00114                         hr = mKeyboard->Acquire();
00115                 return;
00116         }
00117 
00118         if( FAILED(hr) )
00119                 OIS_EXCEPT( E_General, "Win32Keyboard::_readBuffered() >> Problem with Device!" );
00120 
00121         //Update keyboard and modifier states.. And, if listener, fire events
00122         for(unsigned int i = 0; i < entries; ++i )
00123         {
00124                 //If the listener returns false, that means that we are probably deleted...
00125                 //send no more events and just leave as the this pointer is invalid now...
00126                 bool ret = true;
00127                 KeyCode kc = (KeyCode)diBuff[ i ].dwOfs;
00128                         
00129                 //Store result in our keyBuffer too
00130                 KeyBuffer[kc] = static_cast<unsigned char>(diBuff[ i ].dwData);
00131                         
00132                 if( diBuff[ i ].dwData & 0x80 )
00133                 {
00134                         //Turn on modifier
00135                         if( kc == KC_LCONTROL || kc == KC_RCONTROL )
00136                                 mModifiers |= Ctrl;
00137                         else if( kc == KC_LSHIFT || kc == KC_RSHIFT )
00138                                 mModifiers |= Shift;
00139                         else if( kc == KC_LMENU || kc == KC_RMENU )
00140                                 mModifiers |= Alt;
00141 
00142                         if( listener )
00143                                 ret = listener->keyPressed( KeyEvent( this, kc, _translateText(kc) ) );
00144                 }
00145                 else
00146                 {
00147                         //Turn off modifier
00148                         if( kc == KC_LCONTROL || kc == KC_RCONTROL )
00149                                 mModifiers &= ~Ctrl;
00150                         else if( kc == KC_LSHIFT || kc == KC_RSHIFT )
00151                                 mModifiers &= ~Shift;
00152                         else if( kc == KC_LMENU || kc == KC_RMENU )
00153                                 mModifiers &= ~Alt;
00154 
00155                         //Fire off event
00156                         if( listener )
00157                                 ret = listener->keyReleased( KeyEvent( this, kc, 0 ) );
00158                 }
00159 
00160                 if(ret == false)
00161                         break;
00162         }
00163 }
00164 
00165 //--------------------------------------------------------------------------------------------------//
00166 void Win32Keyboard::_read()
00167 {
00168     HRESULT  hr = mKeyboard->GetDeviceState( sizeof(KeyBuffer), &KeyBuffer );
00169 
00170         if( hr == DIERR_INPUTLOST || hr == DIERR_NOTACQUIRED )
00171         {
00172                 hr = mKeyboard->Acquire();
00173                 if (hr != DIERR_OTHERAPPHASPRIO)
00174                         mKeyboard->GetDeviceState(sizeof(KeyBuffer), &KeyBuffer);
00175         }
00176 
00177         //Set Shift, Ctrl, Alt
00178         mModifiers = 0;
00179         if( isKeyDown(KC_LCONTROL) || isKeyDown(KC_RCONTROL) )
00180                 mModifiers |= Ctrl;
00181         if( isKeyDown(KC_LSHIFT) || isKeyDown(KC_RSHIFT) )
00182                 mModifiers |= Shift;
00183         if( isKeyDown(KC_LMENU) || isKeyDown(KC_RMENU) )
00184                 mModifiers |= Alt;
00185 }
00186 
00187 //--------------------------------------------------------------------------------------------------//
00188 int Win32Keyboard::_translateText( KeyCode kc )
00189 {
00190         if( mTextMode == Off )
00191                 return 0;
00192 
00193         BYTE keyState[256];
00194         HKL  layout = GetKeyboardLayout(0);
00195         if( GetKeyboardState(keyState) == 0 )
00196                 return 0;
00197 
00198         unsigned int vk = MapVirtualKeyEx(kc, 3, layout);
00199         if( vk == 0 )
00200                 return 0;
00201 
00202         unsigned char buff[3] = {0,0,0};
00203         int ascii = ToAsciiEx(vk, kc, keyState, (LPWORD) buff, 0, layout);
00204         //WCHAR wide[3];
00205         //int ascii = ToUnicodeEx(vk, kc, keyState, wide, 3, 0, layout);
00206         if(ascii == 1 && deadKey != '\0' )
00207         {
00208                 // A dead key is stored and we have just converted a character key
00209                 // Combine the two into a single character
00210                 WCHAR wcBuff[3] = {buff[0], deadKey, '\0'};
00211                 WCHAR out[3];
00212                 
00213                 deadKey = '\0';
00214                 if(FoldStringW(MAP_PRECOMPOSED, (LPWSTR)wcBuff, 3, (LPWSTR)out, 3))
00215                         return out[0];
00216         }
00217         else if (ascii == 1)
00218         {       // We have a single character
00219                 deadKey = '\0';
00220                 return buff[0];
00221         }
00222         else if(ascii == 2)
00223         {       // Convert a non-combining diacritical mark into a combining diacritical mark
00224                 // Combining versions range from 0x300 to 0x36F; only 5 (for French) have been mapped below
00225                 // http://www.fileformat.info/info/unicode/block/combining_diacritical_marks/images.htm
00226                 switch(buff[0]) {
00227                 case 0x5E: // Circumflex accent: â
00228                         deadKey = 0x302; break;
00229                 case 0x60: // Grave accent: à
00230                         deadKey = 0x300; break;
00231                 case 0xA8: // Diaeresis: ü
00232                         deadKey = 0x308; break;
00233                 case 0xB4: // Acute accent: é
00234                         deadKey = 0x301; break;
00235                 case 0xB8: // Cedilla: ç
00236                         deadKey = 0x327; break;
00237                 default:
00238                         deadKey = buff[0]; break;
00239                 }
00240         }
00241 
00242         return 0;
00243 }
00244 
00245 //--------------------------------------------------------------------------------------------------//
00246 bool Win32Keyboard::isKeyDown( KeyCode key )
00247 {
00248         return (KeyBuffer[key] & 0x80) != 0;
00249 }
00250 
00251 //--------------------------------------------------------------------------------------------------//
00252 const std::string& Win32Keyboard::getAsString( KeyCode kc )
00253 {
00254         char temp[256];
00255 
00256         DIPROPSTRING prop;
00257         prop.diph.dwSize = sizeof(DIPROPSTRING);
00258         prop.diph.dwHeaderSize = sizeof(DIPROPHEADER);
00259         prop.diph.dwObj = static_cast<DWORD>(kc);
00260         prop.diph.dwHow = DIPH_BYOFFSET;
00261 
00262         if ( SUCCEEDED( mKeyboard->GetProperty( DIPROP_KEYNAME, &prop.diph ) ) )
00263         {
00264                 // convert the WCHAR in "wsz" to multibyte
00265                 if ( WideCharToMultiByte( CP_ACP, 0, prop.wsz, -1, temp, sizeof(temp), NULL, NULL) )
00266                         return mGetString.assign( temp );
00267         }
00268 
00269         std::stringstream ss;
00270         ss << "Key_" << (int)kc;
00271         return mGetString.assign( ss.str() );
00272 }
00273 
00274 //--------------------------------------------------------------------------------------------------//
00275 void Win32Keyboard::copyKeyStates( char keys[256] )
00276 {
00277         for(int i = 0; i < 256; ++i)
00278                 keys[i] = KeyBuffer[i] > 0; //Normalise the DX values (0x80)
00279 }
00280 
00281 //--------------------------------------------------------------------------------------------------//
00282 void Win32Keyboard::setBuffered(bool buffered)
00283 {
00284         if( buffered != mBuffered )
00285         {
00286                 if(mKeyboard)
00287                 {
00288                         mKeyboard->Unacquire();
00289                         mKeyboard->Release();
00290                         mKeyboard = 0;
00291                 }
00292                 
00293                 mBuffered = buffered;
00294                 _initialize();
00295         }
00296 }

Generated on Sat Dec 1 20:13:52 2007 for OIS by  doxygen 1.5.4