Hola, pego aquí un temilla que me está dando dolores de cabeza...
Trato de explicar la situación:
Estoy usando DirectInput 8 para una pequeña librería de manejo de entradas. Por ahora no hace mucho, pero ya tengo mapeados los eventos de DirectInput tanto de teclado como de Mouse y Joystick. (No hace falta decir que estoy ya está hecho, es para algo distinto de lo que hace SDL).
Todo funciona a las mil maravillas excepto por un pequeño detalle: Al salir de la aplicación, por alguna razón, la función IDirectInputDevice8::Release, se cuelga si mi ventana perdió el foco, y sólo se cuelga cuando el dispositivo es un Joystick. Si la aplicación no pierde el foco, el release funciona bien; adicionalmente, el Teclado y Mouse se liberan correctamente independientemente de si la ventana perdió o no el foco.
El código para Liberar y Adquirir dispositivos va más o menos así:
Y en la función que procesa los mensajes tengo esto:
Entonces, al momento de cerrar la aplicación, entre las muchas otras cosas que hago es llamar a una función que hace el Release de cada dispositivo que haya sido creado:
El programa se cuelga en la línea: diDevice [Dev]->Release ();
Pero ello sólo ocurre cuando el Dev a liberar es un joystick y la ventana perdió el foco anteriormente.
Alguien se ha enfrentado a algo como esto antes?
Si sirve de algo, pego la función con la que estoy creando los Dispositivos DXI; aclarando que input_device es un enum de los tipos posibles de dispositivos (teclado, mouse, joystick0 a joystick7, ...)
Trato de explicar la situación:
Estoy usando DirectInput 8 para una pequeña librería de manejo de entradas. Por ahora no hace mucho, pero ya tengo mapeados los eventos de DirectInput tanto de teclado como de Mouse y Joystick. (No hace falta decir que estoy ya está hecho, es para algo distinto de lo que hace SDL).
Todo funciona a las mil maravillas excepto por un pequeño detalle: Al salir de la aplicación, por alguna razón, la función IDirectInputDevice8::Release, se cuelga si mi ventana perdió el foco, y sólo se cuelga cuando el dispositivo es un Joystick. Si la aplicación no pierde el foco, el release funciona bien; adicionalmente, el Teclado y Mouse se liberan correctamente independientemente de si la ventana perdió o no el foco.
El código para Liberar y Adquirir dispositivos va más o menos así:
Código [Seleccionar]
map <input_device, LPDIRECTINPUTDEVICE8> diDevice;
void unacquire_devs ()
{
map <input_device, LPDIRECTINPUTDEVICE8>::iterator Pos;
for (Pos = diDevice.begin (); Pos != diDevice.end (); ++Pos)
{
cout << "Unacquiring dev " << Pos->first << endl;
if (Pos->second != NULL)
Pos->second->Unacquire ();
}
}
void acquire_devs ()
{
map <input_device, LPDIRECTINPUTDEVICE8>::iterator Pos;
for (Pos = diDevice.begin (); Pos != diDevice.end (); ++Pos)
Pos->second->Acquire ();
}
Y en la función que procesa los mensajes tengo esto:
Código [Seleccionar]
LRESULT CALLBACK WndProc( HWND hWnd, // Handle For This Window
UINT uMsg, // Message For This Window
WPARAM wParam, // Additional Message Information
LPARAM lParam) // Additional Message Information
{
switch (uMsg) // Check For Windows Messages
{
case WA_INACTIVE:
{
unacquire_devs ();
}
case WM_ACTIVATE: // Watch For Window Activate Message
{
acquire_devs ();
}
// ...
Entonces, al momento de cerrar la aplicación, entre las muchas otras cosas que hago es llamar a una función que hace el Release de cada dispositivo que haya sido creado:
Código [Seleccionar]
bool release_dev (input_device Dev)
{
if (diDevice [Dev] != NULL)
{
diDevice [Dev]->Unacquire ();
diDevice [Dev]->Release ();
diDevice [Dev] = NULL;
return true;
}
return false;
}
void destroy_dx ()
{
map <input_device, LPDIRECTINPUTDEVICE8>::iterator Pos;
unacquire_devs ();
for (Pos = diDevice.begin (); Pos != diDevice.end (); ++Pos)
release_dev (Pos->first);
if (DXInputObj != NULL)
{
DXInputObj->Release ();
DXInputObj = NULL;
}
}
El programa se cuelga en la línea: diDevice [Dev]->Release ();
Pero ello sólo ocurre cuando el Dev a liberar es un joystick y la ventana perdió el foco anteriormente.
Alguien se ha enfrentado a algo como esto antes?
Si sirve de algo, pego la función con la que estoy creando los Dispositivos DXI; aclarando que input_device es un enum de los tipos posibles de dispositivos (teclado, mouse, joystick0 a joystick7, ...)
Código [Seleccionar]
bool open_dev (input_device Dev)
{
GUID DevGUID;
LPCDIDATAFORMAT DevDataFormat;
DIPROPDWORD Props;
DWORD CopLevel;
if (diDevice [Dev] != NULL)
return true;
switch (Dev)
{
case device_keyboard:
DevGUID = GUID_SysKeyboard;
DevDataFormat = &c_dfDIKeyboard;
CopLevel = DISCL_FOREGROUND | DISCL_NONEXCLUSIVE;
break;
case device_mouse:
DevGUID = GUID_SysMouse;
DevDataFormat = &c_dfDIMouse;
CopLevel = DISCL_FOREGROUND | DISCL_NONEXCLUSIVE;
break;
case device_joystick0:
case device_joystick1:
case device_joystick2:
case device_joystick3:
case device_joystick4:
case device_joystick5:
case device_joystick6:
case device_joystick7:
if (AvailJoy.find (Dev) == AvailJoy.end ())
{
seterror ("open_dev: Attempt to open an unavailable joystick");
return false;
}
DevGUID = AvailJoy [Dev];
DevDataFormat = &c_dfDIJoystick2;
CopLevel = DISCL_NONEXCLUSIVE | DISCL_FOREGROUND;
break;
default:
seterror ("open_dev: Attempt to open an unknown device type");
return false;
}
hr = DXInputObj->CreateDevice (DevGUID, &diDevice [Dev], NULL);
if (FAILED(hr))
{
seterror ("open_dev: could not open DirectInput 8 Device");
return false;
}
diDevice [Dev]->SetDataFormat (DevDataFormat);
diDevice [Dev]->SetCooperativeLevel(hWnd, CopLevel);
//We are using Buffered input
Props.diph.dwSize = sizeof(DIPROPDWORD);
Props.diph.dwHeaderSize = sizeof(DIPROPHEADER);
Props.diph.dwObj = 0;
Props.diph.dwHow = DIPH_DEVICE;
Props.dwData = _input_buffer_size;
hr = diDevice [Dev]->SetProperty (DIPROP_BUFFERSIZE, &Props.diph);
if (FAILED(hr))
{
seterror ("open_dev: could not set buffered device");
return false;
}
diDevice [Dev]->Acquire();
return true;
}