共用方式為


C++ (鍵盤、滑鼠和控制器輸入)

本文與舊版 WinRT 原生 API 相關。 針對新的原生應用程式專案,我們建議使用 OpenXR API

本文中的程式碼片段目前示範如何使用 C++/CX,而不是 C++17 相容的 C++/WinRT,如 C++ 全像攝影專案範本中所示。 雖然您需要翻譯程式碼,但概念相當於 C++/WinRT 專案。

訂閱 CoreWindow 輸入事件

鍵盤輸入

在 Windows 全像攝影應用程式範本中,我們包含鍵盤輸入的事件處理常式,就像任何其他 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 全像攝影應用程式範本,以支援按一下滑鼠的方式與按下的手勢相同。 進行這項修改之後,戴著沉浸式頭戴式裝置時按一下滑鼠就會重新置放立方體。

注意

UWP app 也可以使用 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;

重新編譯並重新部署。 請注意,滑鼠點選現在會重新置放沉浸式頭戴式裝置中的 Cube,或已連結藍牙滑鼠的 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變數來新增滑鼠事件。 將此新增至 Update 方法,緊接在檢查 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;

清除主要類別時,別忘了取消註冊事件:

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

重新編譯並重新部署。 您現在可以附加或配對遊戲控制器,並用它來重新置放旋轉立方體。

另請參閱