Compartir a través de


Entrada de teclado, mouse y controlador (C++)

Este artículo se relaciona con las API nativas heredadas de WinRT. En el caso de los nuevos proyectos de aplicaciones nativas, se recomienda usar la API de OpenXR.

Los fragmentos de código de este artículo muestran actualmente el uso de C++/CX en lugar de C++17 compatible con C++/WinRT como se usa en la plantilla de proyecto holográfica de C++. Los conceptos son equivalentes para un proyecto de C++/WinRT, aunque deberá traducir el código.

Suscribirse a eventos de entrada coreWindow

Entrada de teclado

En la plantilla de aplicación Windows Holographic, se incluye un controlador de eventos para la entrada de teclado como cualquier otra aplicación para UWP. La aplicación consume datos de entrada de teclado de la misma manera en Windows Mixed Reality.

Desde 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 del teclado virtual

Para cascos de escritorio envolventes, puede admitir teclados virtuales representados por Windows a través de la vista inmersiva mediante la implementación de CoreTextEditContext. Esto permite a Windows comprender el estado de sus propios cuadros de texto representados por la aplicación, por lo que el teclado virtual puede contribuir correctamente al texto allí.

Para obtener más información sobre cómo implementar la compatibilidad con CoreTextEditContext, vea el ejemplo CoreTextEditContext.

Entrada de mouse

También puedes usar la entrada del mouse, de nuevo a través de los controladores de eventos de entrada de UWP CoreWindow. Aquí se muestra cómo modificar la plantilla de aplicación windows Holographic para admitir clics del mouse de la misma manera que los gestos presionados. Después de realizar esta modificación, un clic del mouse mientras usa un dispositivo de casco envolvente cambiará la posición del cubo.

Nota

Las aplicaciones para UWP también pueden obtener datos XY sin procesar para el mouse mediante la API MouseDevice .

Comience declarando un nuevo controlador OnPointerPressed en AppView.h:

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

En AppView.cpp, agregue este código a SetWindow:

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

A continuación, coloque esta definición para OnPointerPressed en la parte inferior del archivo:

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

El controlador de eventos que acabamos de agregar es un paso a través a la clase principal de plantilla. Vamos a modificar la clase principal para admitir este paso a través. Agregue esta declaración de método público al archivo de encabezado:

// Handle mouse input.
       void OnPointerPressed();

Necesitará también esta variable de miembro privado:

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

Por último, actualizaremos la clase principal con nueva lógica para admitir clics del mouse. Para empezar, agregue este controlador de eventos. Asegúrese de actualizar el nombre de la clase:

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

Ahora, en el método Update, reemplace la lógica existente para obtener una posición de puntero con esto:

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;

Vuelva a compilar y volver a implementar. Tenga en cuenta que el clic del mouse ahora cambiará la posición del cubo en los cascos envolventes o HoloLens con el mouse bluetooth conectado.

Compatibilidad con el controlador de juego

Los controladores de juegos pueden ser una manera divertida y cómoda de permitir al usuario controlar una experiencia inmersiva Windows Mixed Reality.

agregue las siguientes declaraciones de miembro privado a la clase de encabezado del archivo 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;

Inicialice los eventos del controlador para juegos y los controladores para juegos que estén conectados actualmente, en el constructor de la clase 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);
   }

Agregue estos controladores de eventos a la clase principal. Asegúrese de actualizar el nombre de la clase:

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 último, actualice la lógica de entrada para reconocer los cambios en el estado del controlador. Aquí, usamos la misma variable de m_pointerPressed que se describe en la sección anterior para agregar eventos del mouse. Agregue esto al método Update, justo antes de donde comprueba el 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;

No olvide anular el registro de los eventos al limpiar la clase principal:

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

Vuelva a compilar y vuelva a implementar. Ahora puedes conectar, o emparejar, un controlador de juego y usarlo para cambiar la posición del cubo giratorio.

Consulte también