> ## Documentation Index
> Fetch the complete documentation index at: https://docs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Utilisation de plusieurs versions de l'API GameInput dans une même application

> Découvrez comment utiliser QueryInterface pour combiner différentes versions de l'API GameInput, comme v0 et v4, dans la même application.

Chaque version de l'API GameInput, de v0 à v4, définit son propre ensemble d'interfaces COM. Le runtime GameInput implémente toutes les versions sur les mêmes objets sous-jacents; un seul objet, comme un appareil, possède donc une interface v0, une interface v4 et une interface pour chaque version intermédiaire. Pour faire passer un objet d'une version à une autre, appelez [QueryInterface](https://docs.xbox.com/fr-CA/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface\(refiid_void\)) sur celui-ci.

Cela vous permet de :

* Ajouter des fonctionnalités v4 à une application créée avec une version antérieure de l'API, comme v0, sans migrer toute l'application d'un seul coup.
* Appeler des SDK, des intergiciels ou des plug-ins de moteur qui ont été générés avec une version antérieure de GameInput, même lorsque le reste de votre application utilise v4.

## Versions de l'API prises en charge

Un runtime GameInput prend en charge toutes les versions de l'API inférieures ou égales à sa propre version majeure. Par exemple, lorsque le runtime GameInput 4.0 est installé, chaque objet GameInput implémente les interfaces v0, v1, v2, v3 et v4, et votre application peut utiliser n'importe quelle combinaison de celles-ci.

| Runtime installé | Versions de l'API que vous pouvez utiliser |
| - | - |
| 4.x | v0, v1, v2, v3, v4 |
| 3.x | v0, v1, v2, v3 |
| 2.x | v0, v1, v2 |
| 1.x | v0, v1 |

Si vous demandez une version de l'API plus récente que le runtime installé, `QueryInterface` et [GameInputInitialize](https://docs.xbox.com/fr-CA/reference/input/gameinput/functions/gameinputinitialize.md) échouent avec `E_NOINTERFACE`. La version d'API la plus élevée qu'utilise votre application détermine la version minimale du runtime dont elle a besoin.

Sur PC, le runtime installé est le composant redistribuable GameInput ou un runtime que vous déployez avec votre jeu. Pour plus d'informations, consultez [Package NuGet GameInput](https://docs.xbox.com/fr-CA/build/core-features/common/input/overviews/input-nuget.md) et [Chargement latéral de GameInput](https://docs.xbox.com/fr-CA/build/core-features/common/input/overviews/input-agility-redistributable.md). Sur XBOX, le runtime est inclus avec le GDK, et vous pouvez également déployer un runtime plus récent avec votre jeu. Pour plus d'informations, consultez [GameInput sur les consoles XBOX](https://docs.xbox.com/fr-CA/build/core-features/common/input/overviews/input-xbox.md).

## Configurer votre projet

Pour les nouvelles implémentations, utilisez les en-têtes et `GameInput.lib` du plus récent package NuGet [Microsoft.GameInput](https://www.nuget.org/packages/Microsoft.GameInput). Dans le package, `<GameInput.h>` est l'en-tête le plus récent, et chaque en-tête antérieur se trouve dans un dossier versionné, comme `<v0/GameInput.h>` ou `<v2/GameInput.h>`. La bibliothèque exporte [GameInputInitialize](https://docs.xbox.com/fr-CA/reference/input/gameinput/functions/gameinputinitialize.md), qui crée GameInput pour n'importe quelle version de l'API que vous demandez.

Les bibliothèques des versions antérieures, comme celle du GDK, continuent également de fonctionner. Pour plus d'informations, consultez [Conserver une bibliothèque antérieure](#keep-an-earlier-library).

### Inclure l'en-tête v0

À partir de v1, chaque en-tête GameInput déclare ses types dans un espace de noms versionné, comme `GameInput::v4`. L'en-tête v0 déclare plutôt ses types dans l'espace de noms global. Pour utiliser l'en-tête v0 avec l'en-tête le plus récent, placez le code réutilisable suivant dans un en-tête qui vous est propre, comme `GameInputV0.h` :

```cpp theme={null}
// GameInputV0.h: declares the v0 API in the GameInput::v0 namespace
#pragma once

#include <windows.h>
#include <GameInput.h>

// The v0 header isn't namespaced; its dependencies are already included above.
namespace GameInput::v0
{
    // Prevent the legacy typedefs from finding interfaces declared by the latest header.
    struct IGameInput;
    struct IGameInputReading;
    struct IGameInputDevice;
    struct IGameInputDispatcher;
    struct IGameInputForceFeedbackEffect;
    struct IGameInputRawDeviceReport;

    #include <v0/GameInput.h>
}
```

Cet en-tête fonctionne comme suit :

* Il inclut d'abord le plus récent `<GameInput.h>`. Celui-ci déclare l'API la plus récente dans son propre espace de noms et inclut les en-têtes Windows et COM dont dépend l'en-tête v0, de sorte que l'en-tête v0 ne les inclut pas de nouveau à l'intérieur de l'espace de noms.
* Les déclarations anticipées font en sorte que les typedefs de l'en-tête v0 déclarent de nouvelles interfaces dans `GameInput::v0`, au lieu de faire référence aux interfaces que l'en-tête le plus récent a déjà déclarées.
* L'inclusion de `<v0/GameInput.h>` à l'intérieur de l'espace de noms déplace chaque type, énumération et constante v0 dans `GameInput::v0`, comme `GameInput::v0::IGameInput` et `GameInput::v0::GameInputKindGamepad`.

Dans vos fichiers sources v0, incluez `GameInputV0.h` au lieu de `<GameInput.h>`, et ajoutez `using namespace GameInput::v0;` afin que le code existant puisse continuer à utiliser des noms non qualifiés. Tout fichier source qui inclut `GameInputV0.h` peut également utiliser l'API la plus récente au moyen de son nom complet, comme `GameInput::v4::IGameInput`.

## Exemple : Ajouter des fonctionnalités v4 à une application v0

Vous n'avez pas besoin de réécrire votre code v0 pour commencer à utiliser les fonctionnalités v4. Conservez le code v0 dans ses propres fichiers sources, et placez le nouveau code v4 dans des fichiers sources distincts. Transmettez les objets GameInput entre les deux sous forme de `IUnknown*`, et faites en sorte que chaque côté appelle `QueryInterface` pour obtenir la version dont il a besoin.

### Code v0 existant

Le code v0 suivant crée GameInput et lit la manette de jeu. Comparativement au code v0 d'origine, seuls trois éléments changent :

* Il inclut `GameInputV0.h` au lieu de `<GameInput.h>`.
* Il crée GameInput en appelant `GameInputInitialize` avec l'IID v0, car la plus récente bibliothèque n'exporte pas la fonction `GameInputCreate` v0.
* Il appelle le nouveau code v4 lorsque le bouton A est enfoncé.

```cpp theme={null}
// LegacyInput.cpp: existing code that uses the v0 API
#include "GameInputV0.h"

using namespace GameInput::v0;

// Implemented in NewInputFeatures.cpp.
void SetControllerColor(IUnknown* device);

IGameInput* g_gameInput = nullptr;

HRESULT InitializeInput()
{
    return GameInput::v4::GameInputInitialize(__uuidof(IGameInput), reinterpret_cast<void**>(&g_gameInput));
}

void UpdateGamepad()
{
    IGameInputReading* reading = nullptr;
    if (SUCCEEDED(g_gameInput->GetCurrentReading(GameInputKindGamepad, nullptr, &reading)))
    {
        GameInputGamepadState state;
        reading->GetGamepadState(&state);

        if (state.buttons & GameInputGamepadA)
        {
            IGameInputDevice* device = nullptr;
            reading->GetDevice(&device);
            SetControllerColor(device);
            device->Release();
        }

        reading->Release();
    }
}
```

### Nouveau code v4

Le nouveau fichier source inclut l'en-tête v4 et appelle `QueryInterface` sur l'appareil que le code v0 lui transmet. Il change ensuite la couleur du voyant central de la manette avec [IGameInputDevice::SetLightingColor](https://docs.xbox.com/fr-CA/reference/input/gameinput/interfaces/igameinputdevice/methods/igameinputdevice_setlightingcolor.md) et [IGameInputDevice::ApplyLightingColors](https://docs.xbox.com/fr-CA/reference/input/gameinput/interfaces/igameinputdevice/methods/igameinputdevice_applylightingcolors.md), qui sont nouvelles dans v4. Si l'appareil n'a pas de voyant central, l'appel est ignoré.

```cpp theme={null}
// NewInputFeatures.cpp: new code that uses the v4 API
#include <windows.h>
#include <v4/GameInput.h>

using namespace GameInput::v4;

void SetControllerColor(IUnknown* legacyDevice)
{
    IGameInputDevice* device = nullptr;

    // Fails with E_NOINTERFACE if the installed runtime is older than 4.0.
    if (SUCCEEDED(legacyDevice->QueryInterface(IID_PPV_ARGS(&device))))
    {
        device->SetLightingColor({ 0, 255, 0 }, GameInputLightingGroupCenterLight);
        device->ApplyLightingColors();
        device->Release();
    }
}
```

Si `QueryInterface` échoue, le runtime installé ne prend pas en charge v4. Votre code v0 continue de fonctionner, et votre application peut ignorer les fonctionnalités v4.

Lorsque tout votre code utilise v4, vous pouvez supprimer `GameInputV0.h` et les appels à `QueryInterface`.

### Conserver une bibliothèque antérieure

Si vous continuez à effectuer l'édition de liens avec une bibliothèque d'une version antérieure, comme celle du GDK, votre code v0 existant n'a aucunement besoin d'être modifié. Continuez à inclure l'en-tête v0 de cette version et à appeler `GameInputCreate`. Cet appel est transféré au runtime installé; ainsi, lorsque le runtime est de version 4.0 ou ultérieure, l'objet qu'il retourne implémente également les interfaces v4, et le nouveau code v4 présenté précédemment fonctionne sans modification.

Les bibliothèques antérieures n'exportent pas `GameInputInitialize`. Obtenez les interfaces v4 uniquement en appelant `QueryInterface`, et n'appelez pas la fonction `GameInputCreate` v4, qui appelle `GameInputInitialize`.

## Règles pour passer d'une version à l'autre

Les interfaces des différentes versions de l'API portent les mêmes noms, comme `IGameInput` et `IGameInputDevice`, mais ce sont des types différents dotés de méthodes différentes. Un pointeur vers une interface v0 n'est pas un pointeur vers une interface v4, même si les deux font référence au même objet.

> [!NOTE]
>
> Un cast n'est pas la même chose qu'un appel à `QueryInterface`. Utilisez toujours `QueryInterface` pour obtenir une interface d'une autre version de l'API. N'utilisez jamais `static_cast`, `reinterpret_cast` ou un cast de style C pour convertir d'une version à l'autre. Un cast se compile, mais l'appel d'une méthode au moyen du pointeur converti peut appeler la mauvaise méthode, ce qui entraîne un comportement indéfini.

```cpp theme={null}
GameInput::v0::IGameInputDevice* legacyDevice = /* ... */;

// Wrong: compiles, but calls the wrong methods at run time.
auto badDevice = reinterpret_cast<GameInput::v4::IGameInputDevice*>(legacyDevice);

// Correct: asks the object for its v4 interface.
GameInput::v4::IGameInputDevice* device = nullptr;
HRESULT hr = legacyDevice->QueryInterface(IID_PPV_ARGS(&device));
```

Gardez également ces règles à l'esprit :

* **N'incluez pas d'autre en-tête GameInput après l'en-tête v0.** L'en-tête v0 définit ses codes d'erreur, comme `GAMEINPUT_E_DEVICE_DISCONNECTED`, sous forme de macros, et ces macros brisent les déclarations de tout en-tête GameInput inclus après lui. `GameInputV0.h` respecte cette règle en incluant d'abord l'en-tête le plus récent.
* **Les objets retournés utilisent la version que vous avez appelée.** Par exemple, `GetDevice` sur une lecture v4 retourne un appareil v4, et un rappel d'appareil inscrit auprès de l'interface `IGameInput` v4 reçoit des appareils v4. Appelez `QueryInterface` avant de transmettre ces objets à du code qui utilise une autre version.
* **Chaque appel à `QueryInterface` ajoute une référence.** Libérez le pointeur retourné lorsque vous n'en avez plus besoin, comme pour tout autre pointeur d'interface COM.
* **Vérifiez le résultat.** Lorsque vous demandez une version plus récente de l'API, un échec signifie que le runtime installé ne prend pas en charge cette version.
* **Les types v0 de `GameInputV0.h` sont des types C++ distincts.** `GameInput::v0::IGameInput` et l'interface `IGameInput` globale de `<v0/GameInput.h>` seul décrivent la même interface, mais C++ les traite comme des types différents. Si du code existant ou une autre bibliothèque déclare des fonctions avec les types v0 globaux, appelez ces fonctions à partir d'un fichier source qui inclut uniquement `<v0/GameInput.h>`.

## Appeler des SDK qui utilisent une version antérieure de l'API

Certains SDK, intergiciels et plug-ins de moteur sont générés avec une version précise de l'API GameInput et s'attendent à recevoir des interfaces GameInput de cette version. Votre application peut utiliser une version plus récente tout en appelant ces composants. Appelez `QueryInterface` pour obtenir la version qu'attend le composant, puis transmettez ce pointeur.

Placez l'appel dans un fichier source qui inclut le même en-tête GameInput que celui qu'utilise le composant. Dans l'exemple suivant, `ThirdPartySdk.h` déclare `ThirdPartySdkInitialize(GameInput::v2::IGameInput*)`, et le reste de l'application transmet son objet GameInput sous forme de `IUnknown*` :

```cpp theme={null}
// SdkBridge.cpp: calls an SDK that was built against the v2 API
#include <windows.h>
#include <v2/GameInput.h>
#include "ThirdPartySdk.h"

HRESULT InitializeThirdPartySdk(IUnknown* gameInputObject)
{
    GameInput::v2::IGameInput* gameInput = nullptr;
    HRESULT hr = gameInputObject->QueryInterface(IID_PPV_ARGS(&gameInput));
    if (SUCCEEDED(hr))
    {
        ThirdPartySdkInitialize(gameInput);
        gameInput->Release();
    }

    return hr;
}
```

La même approche fonctionne dans l'autre sens. Si un composant fournit à votre application un objet GameInput d'une version antérieure, appelez `QueryInterface` sur celui-ci pour obtenir l'interface v4.

Comme toutes les versions sont implémentées par le même objet, le SDK et votre application partagent les appareils, les lectures et l'état. La version de l'API du SDK doit également être inférieure ou égale à la version du runtime installé.

## Voir aussi

[Gestion des versions de l'API GameInput](https://docs.xbox.com/fr-CA/build/core-features/common/input/overviews/input-versioning.md)\
[Package NuGet GameInput](https://docs.xbox.com/fr-CA/build/core-features/common/input/overviews/input-nuget.md)\
[Chargement latéral de GameInput](https://docs.xbox.com/fr-CA/build/core-features/common/input/overviews/input-agility-redistributable.md)\
[GameInputInitialize](https://docs.xbox.com/fr-CA/reference/input/gameinput/functions/gameinputinitialize.md)\
[Référence de l'API GameInput](https://docs.xbox.com/fr-CA/reference/input/gameinput/gameinput_members.md)


## Related topics

- [Gestion des versions de l'API GameInput](https://docs.xbox.com/fr-CA/build/core-features/common/input/overviews/input-versioning.md)
- [GameInputInitialize](https://docs.xbox.com/fr-CA/reference/input/gameinput/functions/gameinputinitialize.md)
- [GameInput sur les consoles XBOX](https://docs.xbox.com/fr-CA/build/core-features/common/input/overviews/input-xbox.md)
- [GameInputCreate](https://docs.xbox.com/fr-CA/reference/input/gameinput/functions/gameinputcreate.md)
- [IGameInputDevice::GetDeviceRootId](https://docs.xbox.com/fr-CA/reference/input/gameinput/interfaces/igameinputdevice/methods/igameinputdevice_getdevicerootid.md)
