Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





DirectInput: Se cuelga con IDirectInputDevice8::Release

Iniciado por ALRAZ, 28 de Febrero de 2010, 10:32:16 PM

« anterior - próximo »

ALRAZ

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í:


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:

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:



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, ...)


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;
}

[EX3]

Wenas.

Yo en mi libreria simplemente hago la llamada a Unacquire() del dispositivo y acto seguido destruyo su instancia, pero no hago llamada al metodo Release(). De esta forma siempre me ha funcionado de lujo.

Salu2...

P.D.: Tambien debo decir que hago una implementacion algo rara o atipica de DirectInput segun veo en tutoriales y ejemplos de la gente ya que tampoco tengo implementado el metodo CallBack que si venia en todos los tutoriales del SDK de DirectX ni otras cosas que se supone se deberian implementar.
José Miguel Sánchez Fernández
.NET Developer | Game Programmer | Unity Developer

Blog | Game Portfolio | LinkedIn | Twitter | Itch.io | Gamejolt

ALRAZ

Es decir, usar un delete en lugar de Release?

por cierto: gracias por la respuesta :)

[EX3]

De nada :)

Cita de: ALRAZ en 01 de Marzo de 2010, 02:33:12 AM
Es decir, usar un delete en lugar de Release?
Yo soy de BASIC, no se ahora mismo en C++ como destruis instancias de objetos :D (en C# se supone que es un Dispose(), si el objeto lo permite y requiere, e igualarlo a Null creo).

Salu2...
José Miguel Sánchez Fernández
.NET Developer | Game Programmer | Unity Developer

Blog | Game Portfolio | LinkedIn | Twitter | Itch.io | Gamejolt






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.