Partilhar via


Introdução do teclado, rato e controlador (C++)

Este artigo está relacionado com as APIs nativas do WinRT legadas. Para novos projetos de aplicações nativas, recomendamos a utilização da API OpenXR.

Os fragmentos de código neste artigo demonstram atualmente a utilização de C++/CX em vez de C++17 compatíveis com C++/WinRT, conforme utilizado no modelo de projeto holográfico C++. Os conceitos são equivalentes para um projeto C++/WinRT, embora tenha de traduzir o código.

Subscrever eventos de entrada do CoreWindow

Introdução ao teclado

No modelo de aplicação Do Windows Holographic, incluímos um processador de eventos para introdução de teclado, tal como qualquer outra aplicação UWP. A sua aplicação consome dados de entrada de teclado da mesma forma em Windows Mixed Reality.

A partir de AppView.cpp:

// Register for keypress notifications.
   window->KeyDown +=
       ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(this, &AppView::OnKeyPressed);

    …

   // Input event handlers

   void AppView::OnKeyPressed(CoreWindow^ sender, KeyEventArgs^ args)
   {
       //
       // TODO: Respond to keyboard input here.
       //
   }

Entrada de teclado virtual

Para headsets de ambiente de trabalho envolventes, pode suportar teclados virtuais compostos pelo Windows através da sua vista envolvente ao implementar CoreTextEditContext. Isto permite que o Windows compreenda o estado das suas próprias caixas de texto compostas por aplicações, para que o teclado virtual possa contribuir corretamente para o texto aí.

Para obter mais informações sobre como implementar o suporte coreTextEditContext, veja o exemplo CoreTextEditContext.

Entrada do Rato

Também pode utilizar a entrada do rato, novamente através dos processadores de eventos de entrada UWP CoreWindow. Eis como modificar o modelo de aplicação Do Windows Holographic para suportar cliques do rato da mesma forma que os gestos premidos. Depois de efetuar esta modificação, um clique com o rato enquanto utiliza um auricular envolvente irá reposicionar o cubo.

Nota

As aplicações UWP também podem obter dados XY não processados para o rato com a API MouseDevice .

Comece por declarar um novo processador OnPointerPressed no AppView.h:

protected:
       void OnPointerPressed(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::PointerEventArgs^ args);

Em AppView.cpp, adicione este código a SetWindow:

// Register for pointer pressed notifications.
   window->PointerPressed +=
       ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &AppView::OnPointerPressed);

Em seguida, coloque esta definição para OnPointerPressed na parte inferior do ficheiro:

void AppView::OnPointerPressed(CoreWindow^ sender, PointerEventArgs^ args)
   {
       // Allow the user to interact with the holographic world using the mouse.
       if (m_main != nullptr)
       {
           m_main->OnPointerPressed();
       }
   }

O processador de eventos que acabámos de adicionar é um pass-through para a classe principal do modelo. Vamos modificar a classe principal para suportar este pass-through. Adicione esta declaração de método público ao ficheiro de cabeçalho:

// Handle mouse input.
       void OnPointerPressed();

Também irá precisar desta variável de membro privado:

// Keep track of mouse input.
       bool m_pointerPressed = false;

Por fim, iremos atualizar a classe principal com uma nova lógica para suportar cliques do rato. Comece por adicionar este processador de eventos. Certifique-se de que atualiza o nome da classe:

void MyHolographicAppMain::OnPointerPressed()
   {
       m_pointerPressed = true;
   }

Agora, no método Update, substitua a lógica existente para obter uma pose de ponteiro com o seguinte:

SpatialInteractionSourceState^ pointerState = m_spatialInputHandler->CheckForInput();
   SpatialPointerPose^ pose = nullptr;
   if (pointerState != nullptr)
   {
       pose = pointerState->TryGetPointerPose(currentCoordinateSystem);
   }
   else if (m_pointerPressed)
   {
       pose = SpatialPointerPose::TryGetAtTimestamp(currentCoordinateSystem, prediction->Timestamp);
   }
   m_pointerPressed = false;

Recompilar e reimplementar. Tenha em atenção que o clique do rato irá agora reposicionar o cubo no headset envolvente ou no HoloLens com o rato bluetooth ligado.

Suporte do controlador de jogos

Os controladores de jogo podem ser uma forma divertida e conveniente de permitir que o utilizador controle uma experiência Windows Mixed Reality envolvente.

adicione as seguintes declarações de membro privado à classe de cabeçalho do ficheiro principal:

// Recognize gamepads that are plugged in after the app starts.
       void OnGamepadAdded(Platform::Object^, Windows::Gaming::Input::Gamepad^ args);
// Stop looking for gamepads that are unplugged.
       void OnGamepadRemoved(Platform::Object^, Windows::Gaming::Input::Gamepad^ args);
Windows::Foundation::EventRegistrationToken                     m_gamepadAddedEventToken;
       Windows::Foundation::EventRegistrationToken                     m_gamepadRemovedEventToken;
// Keeps track of a gamepad and the state of its A button.
       struct GamepadWithButtonState
       {
           Windows::Gaming::Input::Gamepad^ gamepad;
           bool buttonAWasPressedLastFrame = false;
       };
       std::vector<GamepadWithButtonState>                             m_gamepads;

Inicialize eventos do gamepad e quaisquer gamepads que estejam atualmente anexados no construtor da sua classe principal:

// If connected, a game controller can also be used for input.
   m_gamepadAddedEventToken = Gamepad::GamepadAdded +=
       ref new EventHandler<Gamepad^>(
           bind(&$safeprojectname$Main::OnGamepadAdded, this, _1, _2)
           );
m_gamepadRemovedEventToken = Gamepad::GamepadRemoved +=
       ref new EventHandler<Gamepad^>(
           bind(&$safeprojectname$Main::OnGamepadRemoved, this, _1, _2)
           );
for (auto const& gamepad : Gamepad::Gamepads)
   {
       OnGamepadAdded(nullptr, gamepad);
   }

Adicione estes processadores de eventos à sua classe principal. Certifique-se de que atualiza o nome da classe:

void MyHolographicAppMain::OnGamepadAdded(Object^, Gamepad^ args)
   {
       for (auto const& gamepadWithButtonState : m_gamepads)
       {
           if (args == gamepadWithButtonState.gamepad)
           {
               // This gamepad is already in the list.
               return;
           }
       }
       m_gamepads.push_back({ args, false });
   }
void MyHolographicAppMain::OnGamepadRemoved(Object^, Gamepad^ args)
   {
       m_gamepads.erase(
           std::remove_if(m_gamepads.begin(), m_gamepads.end(), [&](GamepadWithButtonState& gamepadWithState)
               {
                   return gamepadWithState.gamepad == args;
               }),
           m_gamepads.end());
   }

Por fim, atualize a lógica de entrada para reconhecer as alterações no estado do controlador. Aqui, utilizamos a mesma variável de m_pointerPressed abordada na secção acima para adicionar eventos do rato. Adicione isto ao método Update, imediatamente antes do local onde verifica o SpatialPointerPose:

// Check for new input state since the last frame.
   for (auto& gamepadWithButtonState : m_gamepads)
   {
       bool buttonDownThisUpdate = ((gamepadWithButtonState.gamepad->GetCurrentReading().Buttons & GamepadButtons::A) == GamepadButtons::A);
       if (buttonDownThisUpdate && !gamepadWithButtonState.buttonAWasPressedLastFrame)
       {
           m_pointerPressed = true;
       }
       gamepadWithButtonState.buttonAWasPressedLastFrame = buttonDownThisUpdate;
   }
// For context.
   SpatialInteractionSourceState^ pointerState = m_spatialInputHandler->CheckForInput();
   SpatialPointerPose^ pose = nullptr;
   if (pointerState != nullptr)
   {
       pose = pointerState->TryGetPointerPose(currentCoordinateSystem);
   }
   else if (m_pointerPressed)
   {
       pose = SpatialPointerPose::TryGetAtTimestamp(currentCoordinateSystem, prediction->Timestamp);
   }
   m_pointerPressed = false;

Não se esqueça de anular o registo dos eventos ao limpar a classe principal:

if (m_gamepadAddedEventToken.Value != 0)
   {
       Gamepad::GamepadAdded -= m_gamepadAddedEventToken;
   }
   if (m_gamepadRemovedEventToken.Value != 0)
   {
       Gamepad::GamepadRemoved -= m_gamepadRemovedEventToken;
   }

Recompilar e reimplementar. Agora pode anexar ou emparelhar um controlador de jogo e utilizá-lo para reposicionar o cubo giratório.

Ver também