> ## 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.

# Usando várias versões da API GameInput em um aplicativo

> Saiba como usar QueryInterface para combinar diferentes versões da API GameInput, como v0 e v4, no mesmo aplicativo.

Cada versão da API GameInput, de v0 a v4, define seu próprio conjunto de interfaces COM. O runtime do GameInput implementa todas as versões nos mesmos objetos subjacentes, portanto um único objeto, como um dispositivo, tem uma interface v0, uma interface v4 e uma interface para cada versão intermediária. Para alternar um objeto de uma versão para outra, chame [QueryInterface](https://learn.microsoft.com/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface\(refiid_void\)) nele.

Isso permite que você:

* Adicione recursos da v4 a um aplicativo criado com base em uma versão de API anterior, como a v0, sem migrar o aplicativo inteiro de uma só vez.
* Chame SDKs, middleware ou plug-ins de mecanismo que foram compilados com uma versão anterior do GameInput, mesmo quando o restante do seu aplicativo usa a v4.

## Versões de API compatíveis

Um runtime do GameInput é compatível com todas as versões de API menores ou iguais à sua própria versão principal. Por exemplo, com o runtime do GameInput 4.0 instalado, todo objeto do GameInput implementa as interfaces v0, v1, v2, v3 e v4, e seu aplicativo pode usar qualquer combinação delas.

| Runtime instalado | Versões de API que você pode usar |
| - | - |
| 4.x | v0, v1, v2, v3, v4 |
| 3.x | v0, v1, v2, v3 |
| 2.x | v0, v1, v2 |
| 1.x | v0, v1 |

Se você solicitar uma versão de API mais recente do que o runtime instalado, `QueryInterface` e [GameInputInitialize](https://docs.xbox.com/pt-BR/reference/input/gameinput/functions/gameinputinitialize.md) falharão com `E_NOINTERFACE`. A versão de API mais alta que seu aplicativo usa determina a versão mínima do runtime que ele exige.

No PC, o runtime instalado é o redistribuível do GameInput ou um runtime que você implanta com o seu jogo. Para obter mais informações, confira [Pacote NuGet do GameInput](https://docs.xbox.com/pt-BR/build/core-features/common/input/overviews/input-nuget.md) e [Sideload do GameInput](https://docs.xbox.com/pt-BR/build/core-features/common/input/overviews/input-agility-redistributable.md). No XBOX, o runtime está incluído no GDK, e você também pode implantar um runtime mais recente com o seu jogo. Para obter mais informações, confira [GameInput em consoles XBOX](https://docs.xbox.com/pt-BR/build/core-features/common/input/overviews/input-xbox.md).

## Configurar seu projeto

Para novas implementações, use os cabeçalhos e o `GameInput.lib` do pacote NuGet [Microsoft.GameInput](https://www.nuget.org/packages/Microsoft.GameInput) mais recente. No pacote, `<GameInput.h>` é o cabeçalho mais recente, e cada cabeçalho anterior fica em uma pasta com versão, como `<v0/GameInput.h>` ou `<v2/GameInput.h>`. A biblioteca exporta [GameInputInitialize](https://docs.xbox.com/pt-BR/reference/input/gameinput/functions/gameinputinitialize.md), que cria o GameInput para qualquer versão de API que você solicitar.

Bibliotecas de versões anteriores, como a do GDK, também continuam funcionando. Para obter mais informações, confira [Manter uma biblioteca anterior](#keep-an-earlier-library).

### Incluir o cabeçalho v0

A partir da v1, cada cabeçalho do GameInput declara seus tipos em um namespace com versão, como `GameInput::v4`. Já o cabeçalho v0 declara seus tipos no namespace global. Para usar o cabeçalho v0 junto com o cabeçalho mais recente, coloque o seguinte código clichê em um cabeçalho próprio, como `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>
}
```

Esse cabeçalho funciona da seguinte forma:

* Ele inclui primeiro o `<GameInput.h>` mais recente. Isso declara a API mais recente em seu próprio namespace e inclui os cabeçalhos do Windows e do COM dos quais o cabeçalho v0 depende, para que o cabeçalho v0 não os inclua novamente dentro do namespace.
* As declarações antecipadas fazem com que os typedefs do cabeçalho v0 declarem novas interfaces em `GameInput::v0`, em vez de se referirem a interfaces que o cabeçalho mais recente já declarou.
* Incluir `<v0/GameInput.h>` dentro do namespace move todos os tipos, enumerações e constantes da v0 para `GameInput::v0`, como `GameInput::v0::IGameInput` e `GameInput::v0::GameInputKindGamepad`.

Nos seus arquivos de origem da v0, inclua `GameInputV0.h` em vez de `<GameInput.h>` e adicione `using namespace GameInput::v0;` para que o código existente possa continuar usando nomes não qualificados. Qualquer arquivo de origem que inclua `GameInputV0.h` também pode usar a API mais recente pelo nome completo, como `GameInput::v4::IGameInput`.

## Exemplo: adicionar recursos da v4 a um aplicativo v0

Você não precisa reescrever seu código v0 para começar a usar recursos da v4. Mantenha o código v0 em seus próprios arquivos de origem e coloque o novo código v4 em arquivos de origem separados. Passe os objetos do GameInput entre os dois como `IUnknown*` e faça com que cada lado chame `QueryInterface` para obter a versão de que precisa.

### Código v0 existente

O código v0 a seguir cria o GameInput e lê o gamepad. Em comparação com o código v0 original, apenas três coisas mudam:

* Ele inclui `GameInputV0.h` em vez de `<GameInput.h>`.
* Ele cria o GameInput chamando `GameInputInitialize` com o IID da v0, porque a biblioteca mais recente não exporta a função `GameInputCreate` da v0.
* Ele chama o novo código v4 quando o botão A é pressionado.

```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();
    }
}
```

### Novo código v4

O novo arquivo de origem inclui o cabeçalho v4 e chama `QueryInterface` no dispositivo que o código v0 passa. Em seguida, ele altera a cor da luz central do controle com [IGameInputDevice::SetLightingColor](https://docs.xbox.com/pt-BR/reference/input/gameinput/interfaces/igameinputdevice/methods/igameinputdevice_setlightingcolor.md) e [IGameInputDevice::ApplyLightingColors](https://docs.xbox.com/pt-BR/reference/input/gameinput/interfaces/igameinputdevice/methods/igameinputdevice_applylightingcolors.md), que são novos na v4. Se o dispositivo não tiver uma luz central, a chamada será ignorada.

```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();
    }
}
```

Se `QueryInterface` falhar, o runtime instalado não é compatível com a v4. Seu código v0 continua funcionando, e seu aplicativo pode ignorar os recursos da v4.

Quando todo o seu código usar a v4, você poderá remover `GameInputV0.h` e as chamadas para `QueryInterface`.

### Manter uma biblioteca anterior

Se você continuar vinculando uma biblioteca de uma versão anterior, como a do GDK, seu código v0 existente não precisará mudar nada. Continue incluindo o cabeçalho v0 dessa versão e chamando `GameInputCreate`. Essa chamada é encaminhada para o runtime instalado, portanto, quando o runtime for 4.0 ou posterior, o objeto que ele retorna também implementará as interfaces v4, e o novo código v4 mostrado anteriormente funcionará sem alterações.

Bibliotecas anteriores não exportam `GameInputInitialize`. Obtenha interfaces v4 somente chamando `QueryInterface` e não chame o `GameInputCreate` da v4, que chama `GameInputInitialize`.

## Regras para alternar entre versões

Interfaces de diferentes versões de API têm os mesmos nomes, como `IGameInput` e `IGameInputDevice`, mas são tipos diferentes com métodos diferentes. Um ponteiro para uma interface v0 não é um ponteiro para uma interface v4, embora ambos se refiram ao mesmo objeto.

> [!NOTE]
>
> Fazer uma conversão (cast) não é o mesmo que chamar `QueryInterface`. Sempre use `QueryInterface` para obter uma interface de outra versão de API. Nunca use `static_cast`, `reinterpret_cast` ou uma conversão no estilo C para converter entre versões. Uma conversão compila, mas chamar um método por meio do ponteiro convertido pode chamar o método errado, o que leva a um comportamento indefinido.

```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));
```

Lembre-se também destas regras:

* **Não inclua outro cabeçalho do GameInput depois do cabeçalho v0.** O cabeçalho v0 define seus códigos de erro, como `GAMEINPUT_E_DEVICE_DISCONNECTED`, como macros, e essas macros quebram as declarações de qualquer cabeçalho do GameInput incluído depois dele. `GameInputV0.h` segue essa regra incluindo primeiro o cabeçalho mais recente.
* **Os objetos retornados usam a versão que você chamou.** Por exemplo, `GetDevice` em uma leitura v4 retorna um dispositivo v4, e um retorno de chamada de dispositivo registrado com o `IGameInput` da v4 recebe dispositivos v4. Chame `QueryInterface` antes de passar esses objetos para um código que usa outra versão.
* **Cada chamada para `QueryInterface` adiciona uma referência.** Libere o ponteiro retornado quando não precisar mais dele, assim como qualquer outro ponteiro de interface COM.
* **Verifique o resultado.** Quando você solicita uma versão de API mais recente, uma falha significa que o runtime instalado não é compatível com essa versão.
* **Os tipos v0 em `GameInputV0.h` são tipos C++ separados.** `GameInput::v0::IGameInput` e o `IGameInput` global de `<v0/GameInput.h>` sozinho descrevem a mesma interface, mas o C++ os trata como tipos diferentes. Se um código existente ou outra biblioteca declarar funções com os tipos v0 globais, chame essas funções a partir de um arquivo de origem que inclua somente `<v0/GameInput.h>`.

## Chamar SDKs que usam uma versão de API anterior

Alguns SDKs, middleware e plug-ins de mecanismo são compilados com uma versão específica da API GameInput e esperam interfaces do GameInput dessa versão. Seu aplicativo pode usar uma versão mais recente e ainda assim chamar esses componentes. Chame `QueryInterface` para obter a versão que o componente espera e passe esse ponteiro.

Coloque a chamada em um arquivo de origem que inclua o mesmo cabeçalho do GameInput usado pelo componente. No exemplo a seguir, `ThirdPartySdk.h` declara `ThirdPartySdkInitialize(GameInput::v2::IGameInput*)`, e o restante do aplicativo passa seu objeto do GameInput como `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;
}
```

A mesma abordagem funciona na direção oposta. Se um componente fornecer ao seu aplicativo um objeto do GameInput de uma versão anterior, chame `QueryInterface` nele para obter a interface v4.

Como todas as versões são implementadas pelo mesmo objeto, o SDK e o seu aplicativo compartilham dispositivos, leituras e estado. A versão de API do SDK também deve ser menor ou igual à versão do runtime instalado.

## Confira também

[Controle de versão da API do GameInput](https://docs.xbox.com/pt-BR/build/core-features/common/input/overviews/input-versioning.md)\
[Pacote NuGet do GameInput](https://docs.xbox.com/pt-BR/build/core-features/common/input/overviews/input-nuget.md)\
[Sideload do GameInput](https://docs.xbox.com/pt-BR/build/core-features/common/input/overviews/input-agility-redistributable.md)\
[GameInputInitialize](https://docs.xbox.com/pt-BR/reference/input/gameinput/functions/gameinputinitialize.md)\
[Referência da API do GameInput](https://docs.xbox.com/pt-BR/reference/input/gameinput/gameinput_members.md)


## Related topics

- [Controle de versão da API do GameInput](https://docs.xbox.com/pt-BR/build/core-features/common/input/overviews/input-versioning.md)
- [GameInput em consoles XBOX](https://docs.xbox.com/pt-BR/build/core-features/common/input/overviews/input-xbox.md)
- [GameInputInitialize](https://docs.xbox.com/pt-BR/reference/input/gameinput/functions/gameinputinitialize.md)
- [GameInputCreate](https://docs.xbox.com/pt-BR/reference/input/gameinput/functions/gameinputcreate.md)
- [IGameInput (conteúdo da interface)](https://docs.xbox.com/pt-BR/reference/input/gameinput/interfaces/igameinput/igameinput.md)
