Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Некоторые возможности Windows (например, страница пользовательского интерфейса с поддержкой сенсорного ввода) должна выполняться внутри AppContainer. Если вы хотите добавить такие возможности, расширьте настольное приложение с помощью проектов UWP и компонентов среды выполнения Windows.
Во многих случаях вы можете вызывать API среды выполнения Windows непосредственно из классического приложения, поэтому прежде чем ознакомиться с этим руководством, см. статью "Усовершенствование для Windows".
Примечание.
Функции, описанные в этом разделе, требуют, чтобы ваше приложение было упаковано (то есть имело идентификатор пакета во время выполнения). Это включает упакованные приложения (см. Создание нового проекта для упакованного приложения WinUI 3) и упакованные приложения с внешним расположением (см. раздел Предоставление удостоверения пакета путем упаковки с внешним расположением). Также см. Функции, требующие идентичности пакета.
Сначала следует настроить решение
Добавьте в решение один или несколько проектов UWP и компонентов среды выполнения.
Начните с решения, содержащего проект упаковки приложений Windows с ссылкой на ваше настольное приложение.
На этом рисунке показан пример решения.
Если ваше решение не содержит проект упаковки, см. статью "Упаковка классического приложения с помощью Visual Studio".
Настройка настольного приложения
Убедитесь, что ваше настольное приложение имеет ссылки на файлы, необходимые для вызова Windows Runtime API.
Для этого см. инструкции по вызову API среды выполнения Windows в классических приложениях.
Добавление проекта UWP
Добавьте Blank App (универсальное приложение Windows) в ваше решение.
Там вы сможете создать современный пользовательский интерфейс XAML или использовать API, которые выполняются только в процессе UWP.
В проекте упаковки щелкните правой кнопкой мыши узел "Приложения" и нажмите кнопку "Добавить ссылку".
Затем добавьте ссылку на проект UWP.
Решение будет выглядеть следующим образом:
(Необязательно) Создайте компонент среды выполнения Windows
Для некоторых сценариев потребуется добавить код в компонент среды выполнения Windows.
Затем в проекте UWP добавьте ссылку на компонент среды выполнения. Решение будет выглядеть следующим образом:
Создание решения
Убедитесь, что в вашем решении не появляется ошибок. Если вы получаете ошибки, откройте Configuration Manager и убедитесь, что проекты предназначены для той же платформы.
Рассмотрим некоторые действия, которые можно выполнять с проектами UWP и компонентами среды выполнения.
Отображение современного пользовательского интерфейса XAML
В рамках вашего приложения можно включать современные интерфейсы пользователя на основе XAML в ваше настольное приложение. Эти интерфейсы пользователя естественным образом адаптируются под различные размеры и разрешение экрана и поддерживают современные интерактивные модели, в том числе сенсорный и рукописный ввод.
Например, с помощью небольшого количества разметки XAML вы можете предоставить пользователям мощные функции визуализации, связанные с картой.
На рисунке показано приложение Windows Forms, которое открывает современный пользовательский интерфейс на основе XAML, содержащий элементы управления картой.
Примечание.
В этом примере показан пользовательский интерфейс XAML, полученный добавлением проекта UWP в решение. Это стабильный поддерживаемый подход к отображению пользовательских интерфейсов XAML в классическом приложении. Альтернативный вариант — добавление элементов управления XAML UWP непосредственно в классическое приложение с помощью островков XAML. XAML Islands сейчас предоставляется в предварительной версии для разработчиков. Несмотря на то что вы можете опробовать их в своем собственном прототипном коде сейчас, мы не рекомендуем использовать их в производственном коде в настоящее время. В будущих выпусках Windows эти API и элементы управления будут дорабатываться и совершенствоваться. Дополнительные сведения о XAML Islands см. раздел Элементы управления UWP в классических приложениях
Шаблон проектирования
Для отображения пользовательского интерфейса на основе XAML выполните следующие действия:
2️⃣ Создание пользовательского интерфейса XAML
3️⃣ Добавление расширения протокола в проект UWP
4️⃣ Запуск приложения UWP из классического приложения
5️⃣ В проекте UWP отобразите нужную страницу.
Настройте ваше решение
Общие рекомендации по настройке решения см. в разделе "Сначала настройте ваше решение" в начале этого руководства.
Сейчас ваше решение выглядит примерно так:
В этом примере проект Windows Forms называется "Ориентиры " и проект UWP, содержащий пользовательский интерфейс XAML, называется MapUI.
Создание пользовательского интерфейса XAML
Добавьте пользовательский интерфейс XAML в проект UWP Вот код XAML для простой карты.
<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>
Добавление расширения протокола
В обозревателе решений откройте файл package.appxmanifest проекта упаковки в решении и добавьте это расширение.
<Extensions>
<uap:Extension Category="windows.protocol" Executable="MapUI.exe" EntryPoint="MapUI.App">
<uap:Protocol Name="xamluidemo" />
</uap:Extension>
</Extensions>
Задайте имя протокола, введите имя исполняемого файла, созданного проектом UWP, и имя класса для точки входа.
Вы также можете открыть package.appxmanifest в конструкторе, выбрать вкладку "Объявления" и добавить его туда.
Примечание.
Элементы управления картой скачивают данные из Интернета, следовательно, если вы используете такой элемент, необходимо также добавить в манифест возможность internet client.
Запуск приложения UWP
Сначала из настольного приложения создайте URI, содержащий имя протокола и все параметры, которые необходимо передать в приложение UWP. Затем вызовите метод 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);
}
Анализ параметров и отображение страницы
В классе App проекта UWP переопределите обработчик событий OnActivated . Если приложение активируется вашим протоколом, выполните анализ параметров и откройте требуемую страницу.
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();
}
}
}
В коде за вашей страницей XAML переопределите метод OnNavigatedTo
, чтобы использовать параметры, переданные в страницу. В нашем примере мы будем использовать данные широты и долготы, переданные на страницу, чтобы показать расположение на карте.
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);
}
Сделайте ваше настольное приложение получателем данных для обмена
Вы можете сделать ваше настольное приложение целевым объектом для обмена, чтобы пользователи могли легко передавать ему данные, такие как изображения, из других приложений с поддержкой обмена.
Пользователи смогут выбрать ваше приложение, чтобы передать изображения из Microsoft Edge или приложения "Фотографии". Вот пример приложения WPF, которое поддерживает такую возможность.
.
Полный пример см. здесь
Шаблон проектирования
Чтобы сделать ваше приложение целью для обмена, выполните следующие действия:
1️⃣ Добавить расширение целевого объекта для общего доступа
2️⃣ Переопределите обработчик событий OnShareTargetActivated
3️⃣ Добавление расширений рабочего стола в проект UWP
4️⃣ Добавьте расширение полного доверия
5️⃣ Измените настольное приложение, чтобы получить общий файл
Дальнейшие шаги
Добавление расширения цели общего доступа
В Проводнике решений откройте файл package.appxmanifest проекта установки в вашем решении и добавьте расширение целевого объекта для обмена.
<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>
Укажите имя исполняемого файла, созданного проектом UWP, и имя класса точки входа. В этой разметке предполагается, что исполняемый файл для приложения UWP называется ShareTarget.exe
.
Также необходимо указать типы файлов, которые могут быть переданы приложению. В этом примере мы делаем настольное приложение WPF PhotoStoreDemo целевым объектом для растровых изображений, чтобы указать поддерживаемый тип файла Bitmap
.
Переопределите обработчик события OnShareTargetActivated
Переопределите обработчик событий OnShareTargetActivated в классе App проекта UWP.
Этот обработчик событий вызывается, когда пользователи выбирают ваше приложение для обмена своими файлами.
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();
}
}
В этом коде мы сохраняем переданное пользователем изображение в папку локального хранилища приложений. Позже мы изменим настольное приложение, чтобы оно извлекало изображения из этой папки. Настольное приложение может это сделать, так как включено в тот же пакет, что и UWP-приложение.
Добавление расширений настольных приложений в проект UWP
Добавьте расширение Windows Desktop Extensions для UWP в проект приложения UWP. Вы увидите несколько версий расширения (например, 10.0.18362.0 и 10.0.19041.0). Дополнительные сведения о том, как выбрать версию, см. в разделе Расширения SDK и как ссылаться на них.
Добавить расширение процесса полного доверия
В Обозревателе решений откройте файл package.appxmanifest проекта упаковки в вашем решении, а затем добавьте расширение процесса полного доверия рядом с расширением целевой точки общего доступа, которое вы добавили в этот файл ранее.
<Extensions>
...
<desktop:Extension Category="windows.fullTrustProcess" Executable="PhotoStoreDemo\PhotoStoreDemo.exe" />
...
</Extensions>
Это расширение позволит приложению UWP запускать классическое приложение, с которым вы хотите поделиться файлом. В качестве примера мы ссылаемся на исполняемый файл настольного приложения WPF PhotoStoreDemo.
Измените настольное приложение для получения общего файла
Измените настольное приложение так, чтобы оно находило и обрабатывало общий файл. В нашем примере приложение UWP сохранило переданный файл в локальной папке с данными приложения. Поэтому мы изменим настольное приложение WPF PhotoStoreDemo, чтобы извлечь фотографии из этой папки.
Photos.Path = Windows.Storage.ApplicationData.Current.LocalFolder.Path;
Для экземпляров настольного приложения, которые уже запущены пользователем, мы также можем обрабатывать событие FileSystemWatcher и передавать путь к местоположению файла. Любой открытый экземпляр настольного приложения отобразит переданную фотографию.
...
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;
}
}));
}
Создание фоновой задачи
Вы можете добавить фоновую задачу для выполнения кода, даже если приложение приостановлено. Фоновые задачи отлично подходят для небольших задач, не требующих участия пользователя. Например, ваша задача может загружать почту, показывать уведомление о входящем сообщении в чате или реагировать на изменение состояния системы.
Вот пример приложения WPF, которое регистрирует фоновую задачу.
Эта задача создает запрос HTTP и измеряет время получения ответа на этот запрос. Ваши задачи наверняка будут более интересными, но это отличный пример для изучения базового механизма фоновой задачи.
Полный пример см. здесь.
Шаблон проектирования
Чтобы создать фоновую службу, выполните следующие действия:
3️⃣ Регистрация фоновой задачи
Реализация фоновой задачи
Реализуйте фоновую задачу, добавив код в проект компонентов среды выполнения 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;
}
Настройка фоновой задачи
В конструкторе манифестов откройте файл package.appxmanifest проекта упаковки в решении.
На вкладке "Объявления" добавьте объявление фоновых задач .
Затем выберите требуемые свойства. В нашем примере используется свойство Timer .
Укажите полное имя класса в компоненте среды выполнения Windows, который реализует фоновую задачу.
Регистрация фоновой задачи
Добавьте код в проект настольного приложения, который регистрирует фоновую задачу.
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);
}
}
Получение ответов на вопросы
Есть вопросы? Спросите нас на Stack Overflow. Наша команда отслеживает эти теги. Вы также можете спросить нас здесь.
Windows developer