Gérer les modifications d’état des clés matérielles Microsoft Copilot

Cet article explique comment les applications peuvent s’inscrire pour être activées et recevoir des notifications lorsque la touche matérielle Microsoft Copilot ou la combinaison Windows + C est appuyée, maintenue enfoncée, et relâchée. Cette fonctionnalité permet aux applications d’effectuer différentes actions en fonction des modifications d’état clés détectées. Par exemple, une application peut effectuer une activation normale lorsque la touche est pressée une seule fois, mais prendre une capture d’écran lorsque la touche est maintenue enfoncée. Ou bien, une application peut commencer à enregistrer l’audio et afficher un indicateur d’état que l’audio est enregistré lorsque la touche est enfoncée et conservée, puis arrêter l’enregistrement audio lorsque la touche est libérée. La touche doit être enfoncée et conservée pendant au moins 300 ms pour passer à l’état détenu.

Cette fonctionnalité étend les fonctionnalités d'un fournisseur de clé matérielle de base Microsoft Copilot, qui s'enregistre simplement pour être lancé lorsque la touche de matériel est enfoncée. Pour plus d’informations, consultez fournisseurs de clés matérielles Microsoft Copilot.

Le reste de cet article décrit la création d’une application WinUI 3 C# simple qui répond à l’activation lancée par une seule pression ou une pression et une mise en attente du bouton Microsoft Copilot.

Créer un projet

Dans Visual Studio, créez un projet. Pour cet exemple, dans la boîte de dialogue Créer un projet , définissez le filtre de langue sur C# et le type de projet sur WinUI, puis sélectionnez « Application vide WinUI (empaquetée) ».

Ajouter une propriété pour suivre l'état enfoncé de la touche Microsoft Copilot

Dans cet exemple, nous allons créer une propriété appelée État que nous allons utiliser pour afficher l’état d’activation actuel dans l’interface utilisateur. Dans MainWindow.xaml.cs, dans la définition de MainWindow , ajoutez le code suivant pour créer une propriété de chaîne à laquelle nous pouvons établir une liaison dans notre fichier XAML.

// MainWindow.xaml.cs
public event PropertyChangedEventHandler? PropertyChanged;

private void OnPropertyChanged([CallerMemberName] string propertyName = "State")
{
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

public void SetState(string state)
{
    State = state;
}

private string _state;
public string State
{
    get => _state;
    set
    {
        if (_state != value)
        {
            _state = value;
            OnPropertyChanged();
        }
    }
}

Ajoutez un contrôle TextBlock à l’interface utilisateur pour afficher l’état d’activation actuel de l’application. Remplacez l’élément StackPanel par défaut dans MainWindow.xaml par le code suivant.

<!-- MainWindow.xaml -->
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
    <TextBlock Name="KeyStateText" Text="{x:Bind State, Mode=OneWay}" />
</StackPanel>

Enfin, mettez à jour le constructeur MainWindow pour prendre un argument qui définit la propriété State lors de la création de la fenêtre.

// MainWindow.xaml.cs
public MainWindow(string state)
{
    this.InitializeComponent();

    SetState(state);
}

Inscription pour l'activation de l'URI

Le système lance les fournisseurs de clés matérielles Microsoft Copilot à l'aide de l'activation de l'URI. Inscrivez un protocole de lancement en ajoutant l’élément uap :Protocol au manifeste de votre application. Pour plus d’informations sur l’inscription en tant que gestionnaire par défaut d’un schéma d’URI, consultez Gérer l’activation de l’URI.

L’exemple suivant montre uap:Extension inscrivant le schéma URI « myapp-copilothotkey ».

<!-- Package.appxmanifest -->
...
  xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
...

<Extensions> 
  ...
  <uap:Extension Category="windows.protocol">
    <uap:Protocol Name="myapp-copilothotkey"> <!-- app-defined protocol name -->
      <uap:DisplayName>SDK Sample URI Scheme</uap:DisplayName>
    </uap:Protocol>
  </uap:Extension>
  ...

extension d'application Microsoft Copilot pour clé matérielle

Une application doit être empaquetée pour s’inscrire en tant que fournisseur de clés matérielles Microsoft Copilot. Pour plus d’informations sur l’empaquetage d’applications, consultez An vue d’ensemble de l’identité de package dans Windows app. Les fournisseurs de clés matérielles pour Microsoft Copilot déclarent leurs informations d'inscription dans le uap3:AppExtension. L’attribut Name de l’extension doit être défini sur « com.microsoft.windows.copilotkeyprovider ». Pour prendre en charge les modifications d’état clés, les applications doivent fournir des entrées supplémentaires à leur déclaration uap3 :AppExtension .

À l'intérieur de l'élément uap3:AppExtension, veuillez ajouter un élément uap3:Properties avec les éléments enfants PressAndHoldStart et PressAndHoldStop. Le contenu de ces éléments doit être l’URI du schéma de protocole inscrit dans le manifeste à l’étape précédente. Les arguments de chaîne de requête spécifient si l'URI est lancé parce que l'utilisateur a appuyé et maintenu la touche de raccourci ou parce qu'il l'a relâchée. L’application utilise ces valeurs de chaîne de requête pendant l’activation de l’application pour déterminer l’action appropriée à entreprendre. La spécification de l’élément SingleTap est facultative, mais peut être utile pour déterminer si l’application a été lancée à partir de la clé matérielle Copilot.

<!-- Package.appxmanifest -->

<Extensions> 
  ...
  <uap3:Extension Category="windows.appExtension"> 
    <uap3:AppExtension Name="com.microsoft.windows.copilotkeyprovider"  
      Id="MyAppId" 
      DisplayName="App display name" 
      Description="App description" 
      PublicFolder="Public"> 
      <uap3:Properties> 
        <SingleTap>myapp-copilothotkey://?state=Tap</SingleTap>
        <PressAndHoldStart>myapp-copilothotkey://?state=Down</PressAndHoldStart> 
        <PressAndHoldStop>myapp-copilothotkey://?state=Up</PressAndHoldStop>
      </uap3:Properties> 
    </uap3:AppExtension>
  </uap3:Extension> 
  ...

Gérer l’activation de l’URI

Pour détecter si l’application a été activée via l’activation de l’URI, appelez AppInstance.GetActivatedEventArgs et vérifiez si la valeur de la propriété AppActivationArguments.Kind est Protocol. Si l’application a été lancée via l’activation du protocole, vérifiez si le schéma d’URI est identique au nom de protocole que vous avez spécifié dans votre manifeste d’application. Si tous ces tests réussissent, vous savez que votre application a été activée par l’utilisateur appuyant sur la touche matérielle Copilot. À ce stade, vous pouvez analyser la chaîne de requête d’URI et obtenir le paramètre d’état , qui aura les valeurs que vous avez spécifiées dans les éléments PressAndHoldStart et PressAndHoldStop dans le manifeste de l’application.

// App.xaml.cs

protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
{
    var eventargs = AppInstance.GetCurrent().GetActivatedEventArgs();
    string state = "";
    if ((eventargs != null) && (eventargs.Kind == ExtendedActivationKind.Protocol))
    {
        var protocolArgs = (Windows.ApplicationModel.Activation.ProtocolActivatedEventArgs)eventargs.Data;
        WwwFormUrlDecoder decoderEntries = new WwwFormUrlDecoder(protocolArgs.Uri.Query);
        state = Uri.UnescapeDataString(decoderEntries.GetFirstValueByName("state"));
    }
    state = (state == "") ? "Launched" : state;

    m_window = new MainWindow(state);
    m_window.Activate();
}

Importante

Notez que, par défaut, les applications WinUI sont multi-instance, ce qui signifie qu’une nouvelle instance sera lancée chaque fois que la touche de raccourci Microsoft Copilot est enfoncée ou relâchée. Il peut s’agir du comportement souhaité pour de nombreux fournisseurs, mais si vous préférez, vous pouvez mettre à jour votre application pour utiliser une seule instance. Pour plus d’informations, consultez Créer une application WinUI à instance unique avec C#.

Gérer l'invocation rapide du chemin

Outre l'activation URI, les applications peuvent s'enregistrer pour prendre en charge l'invocation rapide, qui permet à une application en cours d'exécution de recevoir des messages concernant l'application matérielle Copilot via des messages de fenêtre. Pour une application en cours d’exécution, cette méthode d’appel est plus rapide que l’activation de l’URI et fournira une meilleure expérience utilisateur, car l’application peut commencer à écouter la parole plus rapidement une fois la touche enfoncée et conservée.

Mettre à jour le fichier manifeste de l'application pour prendre en charge l'invocation rapide du chemin d'accès.

Pour ajouter le support de l'invocation du fast path, mettez à jour l'extension « com.microsoft.windows.copilotkeyprovider » pour ajouter l’attribut MessageWParam aux éléments SingleTap, PressAndHoldStart et PressAndHoldStop. Chaque valeur MessageWParam doit être un entier 32 bits unique, mais les valeurs utilisées sont choisies par l’application. Cet exemple utilise respectivement les valeurs 0, 1 et 2. Ces valeurs seront utilisées ultérieurement dans l’exemple lorsqu’elles sont passées dans le paramètre wParam d’un message Windows pour déterminer l’état actuel appuyé de la touche matérielle Windows Copilot.

<!-- Package.appxmanifest -->

<uap3:Extension Category="windows.appExtension">
  <uap3:AppExtension Name="com.microsoft.windows.copilotkeyprovider"
    Id="MyAppId"
    DisplayName="App display name"
    Description="App description"
    PublicFolder="Public">
    <uap3:Properties>
      <SingleTap MessageWParam="0">myapp-copilothotkey://?state=Tap</SingleTap>
      <PressAndHoldStart MessageWParam="1">myapp-copilothotkey://?state=Down</PressAndHoldStart>
      <PressAndHoldStop MessageWParam="2">myapp-copilothotkey://?state=Up</PressAndHoldStop>
    </uap3:Properties>
  </uap3:AppExtension>
</uap3:Extension>

Accès aux API Win32 pour l'enregistrement de fenêtre

L’activation rapide du chemin d’accès est activée en définissant une propriété sur le IPropertyStore associé à l’une des fenêtres de l’application. Cela nécessite l'accès à certaines API Win32 natives. Cette procédure pas à pas utilise la bibliothèque CsWin32, qui automatise la génération de liaisons C# et est disponible en tant que package NuGet.

Dans Visual Studio, dans Explorateur de solutions, cliquez avec le bouton droit sur votre fichier project, puis sélectionnez Manage NuGet packages... . Sous l’onglet Browse du package manager NuGet, recherchez « cswin32 », puis sélectionnez le package « Microsoft.Windows.CsWin32 », puis cliquez sur *Install.

Une fois le package installé, ajoutez un nouveau fichier texte dans votre répertoire project et nommez-le «NativeMethods.txt». L’outil CsWin32 recherche dans ce fichier une liste des API Win32 pour laquelle il génère des liaisons. Placez les noms d’API suivants dans «NativeMethods.txt».

SUBCLASSPROC

SHGetPropertyStoreForWindow

IPropertyStore

SetWindowSubclass

DefSubclassProc

Inscrire la fenêtre pour l'invocation fastpath de Microsoft Copilot

Ensuite, nous allons mettre à jour la classe MainWindow pour inscrire la fenêtre pour recevoir des appels fastpath à partir de la clé matérielle Copilot.

Tout d’abord, appelez GetWindowHandle pour obtenir un handle HWND vers mainWindow. Appelez SHGetPropertyStoreForWindow pour obtenir le IPropertyStore pour la fenêtre. Veuillez créer une nouvelle PROPERTYKEY et définir le membre fmtid sur le GUID pour l'activation rapide de Windows Copilot. Définissez la valeur de la propriété sur une valeur définie par l’application, qui sera renvoyée à l’application à partir du système lorsque l’état de la clé matérielle change. La valeur définie par l’application est l’ID de message Windows qui doit se trouver dans la plage de WM_APP. Pour plus d’informations, consultez WM_APP. Appelez SetValue , puis appelez Commit pour valider la modification dans le magasin de propriétés.

Enfin, créez un rappel SUBCLASSPROC qui sera appelé lorsque l’état de la clé matérielle change. WindowSubClass est l’implémentation de rappel qui sera affichée à l’étape suivante. Appelez SetWindowSubclass pour inscrire le rappel.

private HWND hWndMain;
private Windows.Win32.UI.Shell.SUBCLASSPROC SubClassDelegate;
public const int WM_COPILOT = 0x8000 + 0x0001;

public MainWindow(string state)
{
    this.InitializeComponent();

    hWndMain = (HWND)WinRT.Interop.WindowNative.GetWindowHandle(this);

    var propertyStoreGUID = new Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99");
    var hr = PInvoke.SHGetPropertyStoreForWindow(hWndMain, in propertyStoreGUID, out var propertyStore);
    var key = new PROPERTYKEY();
    var copilotFastpathGUID = new Guid("38652BCA-4329-4E74-86F9-39CF29345EEA");
    key.fmtid = copilotFastpathGUID;
    key.pid = 0x00000002;
    var value = new PROPVARIANT();
    value.Anonymous.Anonymous.vt = VARENUM.VT_UINT;
    value.Anonymous.decVal = WM_COPILOT;
    ((IPropertyStore)propertyStore).SetValue(in key, in value);
    ((IPropertyStore)propertyStore).Commit();

    SubClassDelegate = new Windows.Win32.UI.Shell.SUBCLASSPROC(WindowSubClass);
    bool bRet = PInvoke.SetWindowSubclass(hWndMain, SubClassDelegate, 0, 0);

    SetState(state);
}

Implémenter le rappel de sous-classe de fenêtre

La dernière étape de cet exemple consiste à implémenter le rappel de sous-classe de fenêtre qui sera appelé chaque fois que l’application est en cours d’exécution et que l’état de la clé matérielle Windows Copilot change. Dans cet exemple, nous vérifions que le message de fenêtre correspond à la valeur WM_COPILOT que nous avons spécifiée lors de la configuration du stockage de propriétés à l’étape précédente. Ensuite, nous vérifions la valeur de l’argument wParam pour voir quelles valeurs nous avons spécifiées avec les attributs MessageWParam dans le manifeste de l’application a été passée. SetState est appelé pour mettre à jour l’interface utilisateur avec l’état actuel.

private LRESULT WindowSubClass(HWND hWnd, uint uMsg, WPARAM wParam, LPARAM lParam, nuint uIdSubclass, nuint dwRefData)
{
    switch (uMsg)
    {
        case WM_COPILOT:
        {
            switch (wParam.Value)
            {
                case 0:
                    SetState("SingleTap");
                    break;
                case 1:
                    SetState("PressAndHold START");
                    break;
                case 2:
                    SetState("PressAndHold END");
                    break;
            }
        }
        break;

    }
    return PInvoke.DefSubclassProc((HWND)hWnd, uMsg, wParam, lParam);

}

Signez votre fournisseur de touche physique Windows Copilot

Les applications de fournisseur doivent être connectées pour être activées en tant que cible de la clé matérielle Microsoft Copilot. Pour plus d’informations sur l’empaquetage et la signature de votre application, consultez Packager une application de bureau ou UWP dans Visual Studio.