Sign in to follow this  
__ROB_D__

[DX9c] - Direct Input Issues [FIXED]

Recommended Posts

Hi guys, Well I'm stumped! I'm using Direct Input (9c) for my game, and it works! The issues comes when the window goes out of focus, and then I return to the window. I lose Keyboard focus, and I'm not able to get it back, but the mouse focus returns. The main game loop I get the input, (checking that the devices is acquired and attempting to reacquire if not). In addition to this in the WindowProc when the WM_ACTIVATEAPP message is true I attempt to require the Devices. One last thing to add to the Bug Pot! This issues ONLY happens with the release build, NOT if I run the Debug build (in or outside the IDE) then I can Alt-Tab without issue. Any Ideas? Thanks, Rob [Edited by - __ROB_D__ on October 14, 2008 8:39:36 AM]

Share this post


Link to post
Share on other sites
Don't do that. DirectInput should never be used for keyboard or mouse input, for many reasons. Including the reason that you don't have to worry about getting focus, because Windows will do that for you without the overhead you're incurring from using DirectInput.

Share this post


Link to post
Share on other sites
Evil Steve : I knew you'd say that! I have already read you rant/comment on Direct Input... But I'd already implemented my input system.
I'm also planning on supporting Joysticks/Game-pads so I figured Direct Input was the way to go.

If I can't find a good solution then I might change the Keyboard system, but it's not top of my todo list.

Still leaves me losing keyboard focus though.

Share this post


Link to post
Share on other sites
Quote:
Original post by __ROB_D__
Evil Steve : I knew you'd say that! I have already read you rant/comment on Direct Input... But I'd already implemented my input system.
I'm also planning on supporting Joysticks/Game-pads so I figured Direct Input was the way to go.

If I can't find a good solution then I might change the Keyboard system, but it's not top of my todo list.

Still leaves me losing keyboard focus though.
Ok, if you insist on using DirectInput for keyboard and mouse input [smile]...

Do you get any relevant debug output? Is Acquire() failing? What cooperative level are you setting for the keyboard and mouse? Are you processing all window messages before doing a single game tick (Instead of calling PeekMessage once, then ticking your game, you should run PeekMessage in a loop to eat up all messages, and then run one game tick)?

Share this post


Link to post
Share on other sites
OK, Keyboard Creation, inside Win32Input_c class


hr = DI8->CreateDevice(GUID_SysKeyboard, &DI8Key, NULL);
if (hr != DI_OK)
{
LastError = 2;
return(false);
}

hr = DI8Key->SetDataFormat(&c_dfDIKeyboard);
if (hr != DI_OK)
{
LastError = 3;
return(false);
}

hr = DI8Key->SetCooperativeLevel(*hWnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE | DISCL_NOWINKEY);
if (hr != DI_OK)
{
LastError = 4;
return(false);
}

// DIPROPDWORD DIPropDWord_Key;
DIPropDWord_Key.dwData = INPUT_KEY_BUFFER_MAX_SIZE;
DIPropDWord_Key.diph.dwHeaderSize = sizeof(DIPROPHEADER);
DIPropDWord_Key.diph.dwHow = DIPH_DEVICE;
DIPropDWord_Key.diph.dwObj = 0;
DIPropDWord_Key.diph.dwSize = sizeof(DIPROPDWORD);
hr = DI8Key->SetProperty(DIPROP_BUFFERSIZE, &DIPropDWord_Key.diph);
if (hr != DI_OK)
{
LastError = 11;
return(false);
}
KeyBuffered = true;

DI8Key->Acquire();




Re-acquired Function Called from WinProc

void Win32Input_c::RestoreFocus()
{

if (DI8)
{

int c = 0;

if(DI8Joy)
{
c = 0;
HRESULT hr = DI8Joy->Acquire();
while (hr == DIERR_INPUTLOST && c < 500)
{
hr = DI8Joy->Acquire();
c++;
}
}

if(DI8Mouse)
{
c = 0;
HRESULT hr = DI8Mouse->Acquire();
while (hr == DIERR_INPUTLOST && c < 500)
{
hr = DI8Mouse->Acquire();
c++;
}
}

if(DI8Key)
{
c = 0;
HRESULT hr = DI8Key->Acquire();
while (hr == DIERR_INPUTLOST && c < 500)
{
hr = DI8Key->Acquire();
c++;
}
}

}

}




And Finally Get Data Functions call from game loop

bool Win32Input_c::GetKeyboardState(Input_Key_State_s &KeyState)
{

if (!DI8Key)
{
if (!CreateKeyboard())
return(false);
}

HRESULT hr;
memset(&KeyState, 0, 256);
hr = DI8Key->GetDeviceState(INPUT_KEY_STATE_SIZE, KeyState.Keys);

if (hr != DI_OK)
{

switch(hr)
{
case DIERR_INPUTLOST:
case DIERR_NOTACQUIRED:
{
if (!DI8Key->Acquire())
{
LastError = 12;
return(false);
}
}break;
case DIERR_NOTINITIALIZED:
{
LastError = 13;
return(false);
}break;
case DIERR_INVALIDPARAM:
{
LastError = 14;
return(false);
}break;
case E_PENDING:
{
LastError = 15;
return(false);
}break;
default:
if (!DI8Key->Acquire())
{
LastError = 16;
return(false);
}
}

}

LastError = 0;
return(true);

}

bool Win32Input_c::GetKeyboardBuffer(Input_Key_Buffer_s &KeyBuffer)
{

if (!DI8Key)
{
if (!CreateKeyboard())
return(false);
}

unsigned long BufferSize = INPUT_KEY_BUFFER_MAX_SIZE;
DIDEVICEOBJECTDATA DIKeyBuffer[INPUT_KEY_BUFFER_MAX_SIZE];
HRESULT hr;

hr = DI8Key->GetDeviceData(sizeof(DIDEVICEOBJECTDATA), DIKeyBuffer, &BufferSize, 0);

if (hr != DI_OK)
{

switch(hr)
{
case DIERR_INPUTLOST:
case DIERR_NOTACQUIRED:
{
if (!DI8Key->Acquire())
{
LastError = 12;
return(false);
}
}break;
case DIERR_NOTINITIALIZED:
{
LastError = 13;
return(false);
}break;
case DIERR_INVALIDPARAM:
{
LastError = 17;
return(false);
}break;
case E_PENDING:
{
LastError = 15;
return(false);
}break;
case DIERR_NOTBUFFERED:
{
KeyBuffered = false;
LastError = 18;
return(false);
}break;
default:
if (!DI8Key->Acquire())
{
LastError = 16;
return(false);
}
}

}

// Copy to Buffer
KeyBuffer.NumberOfEvents = BufferSize;
for (unsigned int i = 0; i < BufferSize; i++)
{
KeyBuffer.Buffer[i].Button = (DIKeyBuffer[i].dwOfs & 0x0000FFFF);
//KeyBuffer.Buffer[i].State = (DIKeyBuffer[i].dwData & 0x0000000F);
KeyBuffer.Buffer[i].State = DIKeyBuffer[i].dwData;
KeyBuffer.Buffer[i].TimeStamp = DIKeyBuffer[i].dwTimeStamp - SystemTime;
KeyBuffer.Buffer[i].Sequence = DIKeyBuffer[i].dwSequence;
}

LastError = 0;
return(true);

}




The code I think is fine, it runs as I expect from a debug build, it's the release build that don't work correct, and it works till focus is lost, the issues is with the restoring focus.

EDIT : Just added a Check to see if the Reacquire return != DI_OK and give me a MessageBox and it don't...! So now I'm even more lost!

Share this post


Link to post
Share on other sites
This doesn't work as you expect:

while (hr == DIERR_INPUTLOST && c < 500)
{
hr = DI8Key->Acquire();
c++;
}

You're not pumping window messages in that loop, so if Acquire fails the first time, there's no reason it'll succeed the next 499 times (Since you need to pump window messages to update the focal status of your window).

Aside from that, you have:

if (!DI8Key->Acquire())
{
LastError = 12;
return(false);
}


Acquire returns DI_OK on success, which has a value of 0. So You're setting LastError and returning false if Acquire() succeeds.

Overall, I'd recommend getting rid of any reference to DI_OK; you should be using the SUCCEEDED and FAILED macros to check for error codes, DI_OK is only one of the 2 billion possible success codes - I know of at least one function that returns S_FALSE on success in some cases, which has the value 1 (Although I can't recall what function that is offhand).

Share this post


Link to post
Share on other sites
O Well,

Thanks for you help... I'm going to leave it for today, and review it all tomorrow.

You've given me a few things to look into...

And if all else fails I can rewrite it using the window message loop!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this