Udostępnij przez


Rozszerz swoją aplikację desktopową o nowoczesne składniki platformy UWP

Niektóre środowiska systemu Windows (na przykład strona interfejsu użytkownika z obsługą dotykową) muszą być uruchamiane wewnątrz aplikacji AppContainer. Jeśli chcesz dodać takie doświadczenia, rozbuduj swoją aplikację klasyczną o projekty platformy uniwersalnej systemu Windows i składniki środowiska uruchomieniowego systemu Windows.

W wielu przypadkach można wywołać interfejsy API środowiska uruchomieniowego systemu Windows bezpośrednio z poziomu aplikacji pulpitowej, więc przed przejrzeniem tego przewodnika zapoznaj się z Ulepszanie dla Windows.

Uwaga / Notatka

Funkcje opisane w tym temacie wymagają, aby aplikacja została spakowana (ma tożsamość pakietu w czasie wykonywania). Obejmuje to aplikacje pakietowe (zobacz Tworzenie nowego projektu dla aplikacji pakietowej WinUI 3 na komputer) oraz aplikacje pakietowe z lokalizacją zewnętrzną (zobacz Przyznanie tożsamości pakietu poprzez pakowanie z lokalizacją zewnętrzną). Zobacz również Funkcje, które wymagają tożsamości pakietu.

Najpierw skonfiguruj rozwiązanie

Dodaj do rozwiązania co najmniej jeden projekt platformy UWP i składniki środowiska uruchomieniowego.

Zacznij od rozwiązania, które zawiera projekt pakietowania aplikacji Windows z odwołaniem do aplikacji desktopowej.

Ten obraz przedstawia przykładowe rozwiązanie.

rozszerzenie projektu uruchamiania

Jeśli twoje rozwiązanie nie zawiera projektu pakowania, zapoznaj się z Zapakuj aplikację desktopową przy użyciu Visual Studio.

Skonfiguruj aplikację na pulpit

Upewnij się, że aplikacja desktopowa zawiera odwołania do plików, które są potrzebne do wywoływania interfejsów API środowiska uruchomieniowego systemu Windows.

Aby to zrobić, zobacz Wywoływanie interfejsów API środowiska uruchomieniowego systemu Windows w aplikacjach klasycznych.

Dodaj projekt UWP

Dodaj pustą aplikację (uniwersalną aplikację systemu Windows) do rozwiązania.

W tym miejscu utworzysz nowoczesny interfejs użytkownika XAML lub użyjesz interfejsów API, które działają tylko w ramach procesu platformy UWP.

Dodawanie nowego projektu

W projekcie pakowania kliknij prawym przyciskiem myszy węzeł Aplikacje, a następnie kliknij Dodaj odwołanie.

Dodaj odwołanie

Następnie dodaj odwołanie do projektu platformy UWP.

Wybierz projekt UWP

Twoje rozwiązanie będzie wyglądać mniej więcej tak:

Rozwiązanie z projektem platformy UWP

(Opcjonalnie) Dodawanie składnika środowiska uruchomieniowego systemu Windows

Aby wykonać niektóre scenariusze, musisz dodać kod do składnika środowiska uruchomieniowego systemu Windows.

usług aplikacji składników środowiska uruchomieniowego

Następnie z projektu platformy UWP dodaj odwołanie do składnika środowiska uruchomieniowego. Twoje rozwiązanie będzie wyglądać mniej więcej tak:

odniesienie do składnika środowiska uruchomieniowego

Tworzenie rozwiązania

Skompiluj rozwiązanie, aby upewnić się, że nie występują żadne błędy. Jeśli wystąpią błędy, otwórz program Configuration Manager i upewnij się, że projekty są przeznaczone dla tej samej platformy.

Menedżer konfiguracji

Przyjrzyjmy się kilku funkcjom, które można wykonać za pomocą projektów platformy UWP i składników środowiska uruchomieniowego.

Pokaż nowoczesny interfejs użytkownika XAML

W ramach procesu tworzenia aplikacji możesz dołączyć nowoczesne interfejsy użytkownika oparte na języku XAML do aplikacji komputerowej. Te interfejsy użytkownika są naturalnie adaptacyjne do różnych rozmiarów ekranu i rozdzielczości oraz obsługują nowoczesne modele interaktywne, takie jak dotyk i atrament.

Na przykład przy niewielkiej ilości znaczników XAML można nadać użytkownikom zaawansowane funkcje wizualizacji związanych z mapą.

Na tej ilustracji przedstawiono aplikację Windows Forms, która otwiera nowoczesny interfejs użytkownika oparty na języku XAML zawierający kontrolkę mapy.

adaptacyjnego projektowania

Uwaga / Notatka

W tym przykładzie pokazano interfejs użytkownika XAML przez dodanie projektu platformy UWP do rozwiązania. Jest to obsługiwane i stabilne podejście do wyświetlania interfejsów użytkownika XAML w aplikacji komputerowej. Alternatywą dla tego podejścia jest dodanie kontrolek XAML platformy UWP bezpośrednio do aplikacji pulpitowej przy użyciu wyspy XAML. Wyspy XAML są obecnie dostępne jako wersja zapoznawcza dla deweloperów. Chociaż zachęcamy do wypróbowania ich we własnym prototypowym kodzie, nie zalecamy używania ich w kodzie produkcyjnym w tej chwili. Te interfejsy API i kontrolki będą nadal dojrzałe i ustabilizowane w przyszłych wersjach systemu Windows. Aby dowiedzieć się więcej na temat wysp XAML, zobacz kontrolki UWP w aplikacjach komputerowych

Wzorzec projektu

Aby wyświetlić interfejs użytkownika oparty na języku XAML, wykonaj następujące czynności:

1️⃣ Konfigurowanie rozwiązania

2️⃣ Tworzenie interfejsu użytkownika XAML

3️⃣ Dodawanie rozszerzenia protokołu do projektu platformy UWP

4️⃣ Uruchamianie aplikacji platformy UWP z poziomu aplikacji klasycznej

5️⃣ W projekcie platformy UWP wyświetl odpowiednią stronę

Konfigurowanie rozwiązania

Aby uzyskać ogólne wskazówki dotyczące sposobu konfigurowania rozwiązania, zobacz sekcję Pierwsze, skonfiguruj rozwiązanie na początku tego przewodnika.

Twoje rozwiązanie będzie wyglądać mniej więcej tak:

Rozwiązanie interfejsu użytkownika XAML

W tym przykładzie projekt Windows Forms nosi nazwę Landmarks (Punkty orientacyjne ), a projekt platformy UWP zawierający interfejs użytkownika XAML nosi nazwę MapUI.

Tworzenie interfejsu użytkownika XAML

Dodaj interfejs użytkownika XAML do projektu platformy UWP. Oto kod XAML dla mapy podstawowej.

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Margin="12,20,12,14">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <maps:MapControl x:Name="myMap" Grid.Column="0" Width="500" Height="500"
                     ZoomLevel="{Binding ElementName=zoomSlider,Path=Value, Mode=TwoWay}"
                     Heading="{Binding ElementName=headingSlider,Path=Value, Mode=TwoWay}"
                     DesiredPitch="{Binding ElementName=desiredPitchSlider,Path=Value, Mode=TwoWay}"
                     HorizontalAlignment="Left"
                     MapServiceToken="<Your Key Goes Here" />
    <Grid Grid.Column="1" Margin="12">
        <StackPanel>
            <Slider Minimum="1" Maximum="20" Header="ZoomLevel" Name="zoomSlider" Value="17.5"/>
            <Slider Minimum="0" Maximum="360" Header="Heading" Name="headingSlider" Value="0"/>
            <Slider Minimum="0" Maximum="64" Header=" DesiredPitch" Name="desiredPitchSlider" Value="32"/>
        </StackPanel>
    </Grid>
</Grid>

Dodawanie rozszerzenia protokołu

W Eksploratorze rozwiązań otwórz plik package.appxmanifest projektu Packaging w swoim rozwiązaniu i dodaj to rozszerzenie.

<Extensions>
  <uap:Extension Category="windows.protocol" Executable="MapUI.exe" EntryPoint="MapUI.App">
    <uap:Protocol Name="xamluidemo" />
  </uap:Extension>
</Extensions>

Nadaj protokółowi nazwę, podaj nazwę pliku wykonywalnego wygenerowanego przez projekt platformy UWP oraz nazwę klasy punktu wejścia.

Możesz również otworzyć package.appxmanifest w projektancie, wybrać kartę Deklaracje, a następnie dodać tam rozszerzenie.

karta deklaracji

Uwaga / Notatka

Kontrolki mapowania pobierają dane z Internetu, więc jeśli go używasz, musisz również dodać możliwość "klienta internetowego" do manifestu.

Uruchamianie aplikacji platformy UWP

Najpierw w aplikacji na komputerze utwórz identyfikator URI zawierający nazwę protokołu i wszystkie parametry, które chcesz przekazać do aplikacji UWP. Następnie wywołaj metodę LaunchUriAsync.


private void Statue_Of_Liberty_Click(object sender, EventArgs e)
{
    ShowMap(40.689247, -74.044502);
}

private async void ShowMap(double lat, double lon)
{
    string str = "xamluidemo://";

    Uri uri = new Uri(str + "location?lat=" +
        lat.ToString() + "&?lon=" + lon.ToString());

    var success = await Windows.System.Launcher.LaunchUriAsync(uri);

}

Analizowanie parametrów i wyświetlanie strony

W klasie App projektu platformy UWP zastąp program obsługi zdarzeń OnActivated. Jeśli aplikacja jest aktywowana przez protokół, przeanalizuj parametry, a następnie otwórz odpowiednią stronę.

protected override void OnActivated(Windows.ApplicationModel.Activation.IActivatedEventArgs e)
{
    if (e.Kind == ActivationKind.Protocol)
    {
        ProtocolActivatedEventArgs protocolArgs = (ProtocolActivatedEventArgs)e;
        Uri uri = protocolArgs.Uri;
        if (uri.Scheme == "xamluidemo")
        {
            Frame rootFrame = new Frame();
            Window.Current.Content = rootFrame;
            rootFrame.Navigate(typeof(MainPage), uri.Query);
            Window.Current.Activate();
        }
    }
}

W kodzie strony XAML zastąpij metodę OnNavigatedTo, aby użyć parametrów przekazanych do strony. W takim przypadku użyjemy szerokości geograficznej i długości geograficznej przekazanej na tej stronie, aby wyświetlić lokalizację na mapie.

protected override void OnNavigatedTo(NavigationEventArgs e)
 {
     if (e.Parameter != null)
     {
         WwwFormUrlDecoder decoder = new WwwFormUrlDecoder(e.Parameter.ToString());

         double lat = Convert.ToDouble(decoder[0].Value);
         double lon = Convert.ToDouble(decoder[1].Value);

         BasicGeoposition pos = new BasicGeoposition();

         pos.Latitude = lat;
         pos.Longitude = lon;

         myMap.Center = new Geopoint(pos);

         myMap.Style = MapStyle.Aerial3D;

     }

     base.OnNavigatedTo(e);
 }

Tworzenie aplikacji komputerowej jako celu udostępniania

Aplikację pulpitową można ustawić jako cel udostępniania, aby użytkownicy mogli łatwo udostępniać dane, takie jak zdjęcia z innych aplikacji, które obsługują udostępnianie.

Na przykład użytkownicy mogą wybrać Twoją aplikację do udostępniania zdjęć z przeglądarki Microsoft Edge oraz aplikacji Zdjęcia. Oto przykładowa aplikacja WPF, która ma tę możliwość.

udział docelowy .

Pełny przykład zobacz tutaj

Wzorzec projektu

Aby aplikacja mogła być celem udostępniania, wykonaj następujące czynności:

1️⃣ Dodaj rozszerzenie celu udostępniania

2️⃣ Przesłoń metodę obsługi zdarzenia OnShareTargetActivated

3️⃣ Dodawanie rozszerzeń pulpitu do projektu platformy UWP

4️⃣ Dodawanie rozszerzenia procesu pełnego zaufania

5️⃣ Modyfikowanie aplikacji desktopowej w celu uzyskania dostępu do pliku udostępnionego

Poniższe kroki

Dodaj rozszerzenie celu udostępniania

W Eksploratorze rozwiązań otwórz plik package.appxmanifest projektu Packaging w swoim rozwiązaniu i dodaj rozszerzenie celu udostępniania.

<Extensions>
      <uap:Extension
          Category="windows.shareTarget"
          Executable="ShareTarget.exe"
          EntryPoint="App">
        <uap:ShareTarget>
          <uap:SupportedFileTypes>
            <uap:SupportsAnyFileType />
          </uap:SupportedFileTypes>
          <uap:DataFormat>Bitmap</uap:DataFormat>
        </uap:ShareTarget>
      </uap:Extension>
</Extensions>  

Podaj nazwę pliku wykonywalnego wygenerowanego przez projekt platformy UWP oraz nazwę klasy punktu wejścia. W tym znaczniku przyjęto założenie, że nazwa pliku wykonywalnego dla aplikacji platformy UWP to ShareTarget.exe.

Należy również określić typy plików, które mogą być udostępniane aplikacji. W tym przykładzie tworzymy z aplikacji klasycznej WPF PhotoStoreDemo obiekt docelowy udostępniania dla obrazów map bitowych, dlatego określamy Bitmap dla obsługiwanego typu pliku.

Zastąpij program obsługi zdarzeń OnShareTargetActivated

Zastąp program obsługi zdarzeń OnShareTargetActivated w klasie App projektu platformy UWP.

Ta procedura obsługi zdarzeń jest wywoływana, gdy użytkownicy wybierają aplikację do udostępniania swoich plików.


protected override void OnShareTargetActivated(ShareTargetActivatedEventArgs args)
{
    shareWithDesktopApplication(args.ShareOperation);
}

private async void shareWithDesktopApplication(ShareOperation shareOperation)
{
    if (shareOperation.Data.Contains(StandardDataFormats.StorageItems))
    {
        var items = await shareOperation.Data.GetStorageItemsAsync();
        StorageFile file = items[0] as StorageFile;
        IRandomAccessStreamWithContentType stream = await file.OpenReadAsync();

        await file.CopyAsync(ApplicationData.Current.LocalFolder);
            shareOperation.ReportCompleted();

        await FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync();
    }
}

W tym kodzie zapisujemy obraz udostępniany przez użytkownika do lokalnego folderu aplikacji. Później zmodyfikujemy aplikację klasyczną, aby ściągała obrazy z tego samego folderu. Aplikacja klasyczna może to zrobić, ponieważ jest ona zawarta w tym samym pakiecie co aplikacja platformy UWP.

Dodawanie rozszerzeń pulpitu do projektu platformy UWP

Dodaj rozszerzenia Pulpitu Windows dla UWP do projektu aplikacji UWP. Zobaczysz więcej niż jedną wersję rozszerzenia (na przykład 10.0.18362.0 i 10.0.19041.0). Aby uzyskać informacje o sposobie wybierania wersji, zobacz SDK rozszerzenia , oraz o sposobie odwołania się do nich,.

rozszerzenie desktopu

Dodawanie rozszerzenia pełnego procesu zaufania

W Eksploratorze rozwiązań otwórz plik package.appxmanifest projektu Pakowanie w swoim rozwiązaniu, a następnie dodaj rozszerzenie procesu pełnego zaufania obok rozszerzenia docelowego, które dodałeś wcześniej.

<Extensions>
  ...
      <desktop:Extension Category="windows.fullTrustProcess" Executable="PhotoStoreDemo\PhotoStoreDemo.exe" />
  ...
</Extensions>  

To rozszerzenie umożliwi aplikacji UWP uruchomienie klasycznej aplikacji desktopowej, do której chcesz przekazać plik. Na przykład odwołujemy się do pliku wykonywalnego aplikacji klasycznej WPF PhotoStoreDemo.

Zmodyfikuj aplikację desktopową, aby uzyskać udostępniony plik

Zmodyfikuj aplikację klasyczną, aby znaleźć i przetworzyć udostępniony plik. W tym przykładzie aplikacja platformy UWP przechowywała plik udostępniony w lokalnym folderze danych aplikacji. W związku z tym zmodyfikujemy aplikację desktopową WPF PhotoStoreDemo w celu pobierania zdjęć z tego folderu.

Photos.Path = Windows.Storage.ApplicationData.Current.LocalFolder.Path;

W przypadku wystąpień aplikacji desktopowej, które są już otwarte przez użytkownika, możemy również obsługiwać zdarzenie FileSystemWatcher i przekazać ścieżkę do lokalizacji pliku. Dzięki temu wszystkie otwarte wystąpienia aplikacji komputerowej będą pokazywać udostępnione zdjęcie.

...

   FileSystemWatcher watcher = new FileSystemWatcher(Photos.Path);

...

private void Watcher_Created(object sender, FileSystemEventArgs e)
{
    // new file got created, adding it to the list
    Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(() =>
    {
        if (File.Exists(e.FullPath))
        {
            ImageFile item = new ImageFile(e.FullPath);
            Photos.Insert(0, item);
            PhotoListBox.SelectedIndex = 0;
            CurrentPhoto.Source = (BitmapSource)item.Image;
        }
    }));
}

Tworzenie zadania w tle

Dodasz zadanie w tle, aby uruchomić kod nawet wtedy, gdy aplikacja jest zawieszona. Zadania w tle doskonale nadają się do wykonywania małych zadań, które nie wymagają interakcji z użytkownikiem. Na przykład zadanie może pobrać pocztę, wyświetlić wyskakujące powiadomienie o przychodzącej wiadomości czatu lub zareagować na zmianę stanu systemu.

Oto przykładowa aplikacja WPF, która rejestruje zadanie w tle.

zadanie w tle

Zadanie wysyła żądanie HTTP i mierzy czas potrzebny na otrzymanie odpowiedzi. Twoje zadania będą prawdopodobnie znacznie bardziej interesujące, ale ten przykład doskonale nadaje się do nauki podstawowej mechaniki zadania w tle.

Można zobaczyć kompletny przykład tutaj.

Wzorzec projektu

Aby utworzyć usługę w tle, wykonaj następujące czynności:

1️⃣ Zaimplementuj zadanie w tle

2️⃣ Konfigurowanie zadania w tle

3️⃣ Zarejestruj zadanie w tle

Wdrażaj zadanie w tle

Zaimplementuj zadanie w tle, dodając kod do projektu składnika Środowiska uruchomieniowego systemu Windows.

public sealed class SiteVerifier : IBackgroundTask
{
    public async void Run(IBackgroundTaskInstance taskInstance)
    {

        taskInstance.Canceled += TaskInstance_Canceled;
        BackgroundTaskDeferral deferral = taskInstance.GetDeferral();
        var msg = await MeasureRequestTime();
        ShowToast(msg);
        deferral.Complete();
    }

    private async Task<string> MeasureRequestTime()
    {
        string msg;
        try
        {
            var url = ApplicationData.Current.LocalSettings.Values["UrlToVerify"] as string;
            var http = new HttpClient();
            Stopwatch clock = Stopwatch.StartNew();
            var response = await http.GetAsync(new Uri(url));
            response.EnsureSuccessStatusCode();
            var elapsed = clock.ElapsedMilliseconds;
            clock.Stop();
            msg = $"{url} took {elapsed.ToString()} ms";
        }
        catch (Exception ex)
        {
            msg = ex.Message;
        }
        return msg;
    }

Konfigurowanie zadania w tle

W projektancie manifestu otwórz plik package.appxmanifest projektu Packaging w rozwiązaniu.

Na karcie Deklaracje dodaj deklarację zadań w tle .

Opcja zadania w tle

Następnie wybierz żądane właściwości. W naszym przykładzie użyto właściwości czasomierza.

właściwości czasomierza

Podaj w pełni kwalifikowaną nazwę klasy w składniku środowiska uruchomieniowego systemu Windows, który implementuje zadanie w tle.

Określanie punktu wejścia

Zarejestruj zadanie w tle

Dodaj kod do projektu aplikacji komputerowej, który rejestruje zadanie w tle.

public void RegisterBackgroundTask(String triggerName)
{
    var current = BackgroundTaskRegistration.AllTasks
        .Where(b => b.Value.Name == triggerName).FirstOrDefault().Value;

    if (current is null)
    {
        BackgroundTaskBuilder builder = new BackgroundTaskBuilder();
        builder.Name = triggerName;
        builder.SetTrigger(new MaintenanceTrigger(15, false));
        builder.TaskEntryPoint = "HttpPing.SiteVerifier";
        builder.Register();
        System.Diagnostics.Debug.WriteLine("BGTask registered:" + triggerName);
    }
    else
    {
        System.Diagnostics.Debug.WriteLine("Task already:" + triggerName);
    }
}

Znajdowanie odpowiedzi na pytania

Masz pytania? Zapytaj nas w witrynie Stack Overflow. Nasz zespół monitoruje te tagi . Możesz również zapytać nas tutaj .