キーボード、マウス、およびコントローラー入力 (C++)

この記事は、従来の WinRT ネイティブ API に関連しています。 新しいネイティブ アプリ プロジェクトの場合は、OpenXR API を使用することをお勧めします。

この記事のコード スニペットは、現在、C++ ホログラフィック プロジェクト テンプレートで使用されている C++17 準拠の C++/WinRT ではなく、C++/CX の使用を示しています。 概念は C++/WinRT プロジェクトと同等ですが、コードを翻訳する必要があります。

CoreWindow 入力イベントをサブスクライブする

キーボード入力

Windows Holographic アプリ テンプレートには、他の UWP アプリと同様に、キーボード入力用のイベント ハンドラーが含まれています。 お使いのアプリでは、Windows Mixed Reality と同じ方法でキーボード入力データを使用します。

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.
       //
   }

仮想キーボード入力

イマーシブデスクトップヘッドセットの場合、 CoreTextEditContext を実装することで、イマーシブビュー上で Windows によってレンダリングされた仮想キーボードをサポートできます。 これによりWindowsは、アプリでレンダリングされたテキストボックスの状態を認識できるようになり、仮想キーボードがテキストに正しく反映されるようになります。

CoreTextEditContext サポートの実装の詳細については、CoreTextEditContext のサンプルを参照してください。

マウス入力

また、UWP CoreWindow 入力イベント ハンドラーを使用して、マウス入力を再度使用することもできます。 押したジェスチャと同じ方法でマウス クリックをサポートするように、Windows Holographic アプリ テンプレートを変更する方法は次のとおりです。 この変更を行った後、イマーシブ ヘッドセット デバイスを装着した状態でマウスをクリックすると、キューブの位置が変更されます。

Note

UWP アプリでは、MouseDevice API を使用して、マウスの生 XY データを取得することもできます。

AppView.hで新しいOnPointerPressedハンドラーを宣言することから始めます。

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

AppView.cpp で、次のコードを SetWindow に追加します。

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

次に、OnPointerPressed の次の定義をファイルの最後に配置します。

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

追加したイベント ハンドラーは、テンプレートのメイン クラスへのパススルーです。 このパススルーをサポートするようにメイン クラスを変更してみましょう。 このパブリック メソッド宣言をヘッダー ファイルに追加します。

// Handle mouse input.
       void OnPointerPressed();

このプライベート メンバー変数も必要になります。

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

最後に、マウス クリックをサポートする新しいロジックでメイン クラスを更新します。 このイベントハンドラーを追加することから始めます。 クラス名を必ず更新してください。

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

ここで、Update メソッドで、ポインターポーズを取得するための既存のロジックを次のように置き換えます。

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;

再コンパイルして再デプロイします。 マウスをクリックすると、イマーシブ ヘッドセット、または Bluetooth マウスが接続された HoloLens でキューブの位置が変更されることに注意してください。

ゲーム コントローラーのサポート

ゲーム コントローラーは、ユーザーがイマーシブ Windows Mixed Reality エクスペリエンスをコントロールできるようにするための楽しく便利な方法です。

次のプライベートメンバー宣言をメインファイルのヘッダークラスに追加します。

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

メイン クラスのコンストラクターで、ゲームパッド イベント、および現在アタッチ状態ゲームパッドのを初期化します。

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

これらのイベント ハンドラーをメイン クラスに追加します。 クラス名を必ず更新してください。

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

最後に、入力ロジックを更新して、コントローラーの状態の変化を認識します。 ここでは、マウスイベントを追加するために、上記のセクションで説明したものと同じ m_pointerPressed 変数を使用します。 SpatialPointerPose をチェックする直前の Update メソッドに次を追加します。

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

メイン クラスをクリーンアップするときは、必ずイベントを登録解除してください。

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

再コンパイルして再デプロイします。 これで、ゲームコントローラを添付するかペアリングし、それを使用して回転する立方体の位置を変更できます。

関連項目