實作 3D 應用程式啟動器 (Win32 應用程式)

注意

此功能僅適用于執行最新 Windows 測試 人員正式發行前小眾測試版的電腦, (RS5) 、組建 17704 和更新版本。

Windows Mixed Reality首頁是使用者在啟動應用程式之前登陸的起點。 根據預設,您必須從頭戴式裝置外部啟動沉浸式 Win32 VR 應用程式和遊戲,且不會出現在 Windows Mixed Reality [開始] 功能表的 [所有應用程式] 清單中。 如果您遵循本文中的指示來實作 3D 應用程式啟動器,您可以從 Windows Mixed Reality [開始] 功能表和主環境內啟動沉浸式 Win32 VR 體驗。

這只適用于在串流外部散發的沈浸式 Win32 VR 體驗。 針對透過串流散發的 VR 體驗,我們已更新適用于「串流VR Beta」的Windows Mixed Reality,以及最新的 Windows 測試人員 RS5 正式發行前小眾測試版,讓「所有應用程式」清單中的 [開始] 功能表自動顯示「所有應用程式」清單中的「串流VR」Windows Mixed Reality 標題。 換句話說,本文所述的方法對「串流VR」標題而言是不必要的,而且將會由「串流VR Beta」功能的Windows Mixed Reality覆寫。

3D 應用程式啟動器建立程式

建立 3D 應用程式啟動器有三個步驟:

  1. 設計和概念
  2. 模型化和匯出
  3. 將它整合到您的應用程式 (本文)

應使用Windows Mixed Reality撰寫指導方針撰寫 3D 資產作為應用程式的啟動器,以確保相容性。 不符合此撰寫規格的資產將不會在Windows Mixed Reality首頁中轉譯。

設定 3D 啟動器

如果您為 Win32 應用程式建立 3D 應用程式啟動器,則會出現在 Windows Mixed Reality [開始] 功能表上的 [所有應用程式] 清單中。 若要這樣做,請遵循下列步驟來建立參考 3D 應用程式啟動器的 Visual Elements 資訊清單 XML 檔案:

  1. 建立 3D 應用程式啟動器資產 GLB 檔案 (請參閱 模型化和匯出) 。
  2. 為您的應用程式建立 Visual Elements 資訊清單
    1. 您可以從 下列範例開始。 如需詳細資訊,請參閱完整的 Visual Elements 資訊清單 檔。
    2. 使用您應用程式的 PNG/JPG/GIF 更新 Square150x150LogoSquare70x70Logo
      • 這些會用於Windows Mixed Reality [所有應用程式] 清單中的應用程式 2D 標誌,以及桌面上的 [開始] 功能表。
      • 檔案路徑是以包含 Visual Elements 資訊清單的資料夾為基礎。
      • 您仍然需要透過標準機制為您的應用程式提供桌面 \[開始\] 功能表圖示。 這可以直接位於可執行檔或您建立的快捷方式中。 例如,透過 IShellLink::SetIconLocation。
      • 選: 如果您想要 MRT 為不同的解析度縮放比例和高對比主題提供多個資產大小,則可以使用 resources.pri 檔案。
    3. 更新 MixedRealityModel 路徑 以指向 3D 應用程式啟動器的 GLB
    4. 以與可執行檔相同的名稱儲存檔案,副檔名為 「.VisualElementsManifest.xml」,並將它儲存在相同的目錄中。 例如,針對可執行檔 「contoso.exe」,隨附的 XML 檔案會命名為 「contoso.visualelementsmanifest.xml」。
  3. 將快捷方式 新增至桌面 Windows [開始] 功能表。 如需 C++ 實作範例,請參閱 下列範例
    • 在 %ALLUSERSPROFILE%\Microsoft\Windows\Start Menu\Programs (電腦) 或 %APPDATA%\Microsoft\Windows\Start Menu\Programs (user)
    • 如果更新變更您的視覺元素資訊清單或它所參考的資產,更新程式或安裝程式應該更新快捷方式,以便重新分析資訊清單並更新快取的資產。
  4. 選: 例如,如果您的桌面快捷方式未直接指向應用程式的 EXE (,如果它叫用自訂通訊協定處理常式,例如 「myapp://」) ,[開始] 功能表就不會自動找到應用程式的VisualElementsManifest.xml檔案。 若要解決此問題,快捷方式應該使用 System.AppUserModel.VisualElementsManifestHintPath () 指定 Visual Elements 資訊清單的檔案路徑。 這可以使用與 System.AppUserModel.ID 相同的技術,在快捷方式中設定。 您不需要使用 System.AppUserModel.ID,但如果您想要讓快捷方式符合應用程式的明確應用程式使用者模型識別碼,則可以這麼做。 如需 C++ 範例,請參閱下方 的範例應用程式啟動器快捷方式建立 一節。

範例視覺效果元素資訊清單

<Application xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance">
  <VisualElements
    ShowNameOnSquare150x150Logo="on"
    Square150x150Logo="YOUR_APP_LOGO_150X150.png"
    Square70x70Logo=" YOUR_APP_LOGO_70X70.png"
    ForegroundText="light"
    BackgroundColor="#000000">
    <MixedRealityModel Path="YOUR_3D_APP_LAUNCHER_ASSET.glb">
        <SpatialBoundingBox Center="0,0,0" Extents="Auto" />
    </MixedRealityModel>
  </VisualElements>
</Application>

範例應用程式啟動器快捷方式建立

下列範例程式碼示範如何在 C++ 中建立快捷方式,包括覆寫 Visual Elements 資訊清單 XML 檔案的路徑。 請注意,只有在快捷方式未直接指向與資訊清單相關聯的 EXE (時,才需要覆寫,例如,您的快捷方式會使用自訂通訊協定處理常式,例如 「myapp://」) 。

樣品。 (C++) 建立 LNK 快捷方式

#include <windows.h>
#include <propkey.h>
#include <shlobj_core.h>
#include <shlwapi.h>
#include <propvarutil.h>
#include <wrl.h>

#include <memory>

using namespace Microsoft::WRL;

#define RETURN_IF_FAILED(x) do { HRESULT hr = x; if (FAILED(hr)) { return hr; } } while(0)
#define RETURN_IF_WIN32_BOOL_FALSE(x) do { DWORD res = x; if (res == 0) { return HRESULT_FROM_WIN32(GetLastError()); } } while(0)

int wmain()
{
    RETURN_IF_FAILED(CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED));

    ComPtr<IShellLink> shellLink;
    RETURN_IF_FAILED(CoCreateInstance(__uuidof(ShellLink), nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&shellLink)));
    RETURN_IF_FAILED(shellLink->SetPath(L"MyLauncher://launch/app-identifier"));

    // It is also possible to use an icon file in another location. For example, "C:\Program Files (x86)\MyLauncher\assets\app-identifier.ico".
    RETURN_IF_FAILED(shellLink->SetIconLocation(L"C:\\Program Files (x86)\\MyLauncher\\apps\\app-identifier\\game.exe", 0 /*iIcon*/));

    ComPtr<IPropertyStore> propStore;
    RETURN_IF_FAILED(shellLink.As(&propStore));

    {
        // Optional: If the application has an explict Application User Model ID, then you should usually specify it in the shortcut.
        PROPVARIANT propVar;
        RETURN_IF_FAILED(InitPropVariantFromString(L"ExplicitAppUserModelID", &propVar));
        RETURN_IF_FAILED(propStore->SetValue(PKEY_AppUserModel_ID, propVar));
        PropVariantClear(&propVar);
    }

    {
        // A hint path to the manifest is only necessary if the target path of the shortcut is not a file path to the executable.
        // By convention the manifest is named <executable name>.VisualElementsManifest.xml and is in the same folder as the executable
        // (and resources.pri if applicable). Assets referenced by the manifest are relative to the folder containing the manifest.

        //
        // PropKey.h
        //
        //  Name:     System.AppUserModel.VisualElementsManifestHintPath -- PKEY_AppUserModel_VisualElementsManifestHintPath
        //  Type:     String -- VT_LPWSTR  (For variants: VT_BSTR)
        //  FormatID: {9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}, 31
        //  
        //  Suggests where to look for the VisualElementsManifest for a Win32 app
        //
        // DEFINE_PROPERTYKEY(PKEY_AppUserModel_VisualElementsManifestHintPath, 0x9F4C2855, 0x9F79, 0x4B39, 0xA8, 0xD0, 0xE1, 0xD4, 0x2D, 0xE1, 0xD5, 0xF3, 31);
        // #define INIT_PKEY_AppUserModel_VisualElementsManifestHintPath { { 0x9F4C2855, 0x9F79, 0x4B39, 0xA8, 0xD0, 0xE1, 0xD4, 0x2D, 0xE1, 0xD5, 0xF3 }, 31 }

        PROPVARIANT propVar;
        RETURN_IF_FAILED(InitPropVariantFromString(L"C:\\Program Files (x86)\\MyLauncher\\apps\\app-identifier\\game.visualelementsmanifest.xml", &propVar));
        RETURN_IF_FAILED(propStore->SetValue(PKEY_AppUserModel_VisualElementsManifestHintPath, propVar));
        PropVariantClear(&propVar);
    }

    constexpr PCWSTR shortcutPath = L"%APPDATA%\\Microsoft\\Windows\\Start Menu\\Programs\\game.lnk";
    const DWORD requiredBufferLength = ExpandEnvironmentStrings(shortcutPath, nullptr, 0);
    RETURN_IF_WIN32_BOOL_FALSE(requiredBufferLength);

    const auto expandedShortcutPath = std::make_unique<wchar_t[]>(requiredBufferLength);
    RETURN_IF_WIN32_BOOL_FALSE(ExpandEnvironmentStrings(shortcutPath, expandedShortcutPath.get(), requiredBufferLength));

    ComPtr<IPersistFile> persistFile;
    RETURN_IF_FAILED(shellLink.As(&persistFile));
    RETURN_IF_FAILED(persistFile->Save(expandedShortcutPath.get(), FALSE));

    return 0;
}

樣品。URL 啟動器快捷方式

[{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}]
Prop31=C:\Program Files (x86)\MyLauncher\apps\app-identifier\game.visualelementsmanifest.xml
Prop5=ExplicitAppUserModelID

[{000214A0-0000-0000-C000-000000000046}]
Prop3=19,0

[InternetShortcut]
IDList=
URL=MyLauncher://launch/app-identifier
IconFile=C:\Program Files (x86)\MyLauncher\apps\app-identifier\game.exe
IconIndex=0

另請參閱