Создание и регистрация Metro style компонента для WinRT

    Официальный релиз Windows 8 приближается с каждым днём, и всё больше разработчиков задумывается о том, чтобы создать своё приложение в стиле Metro. А если же вы делаете сразу несколько таких приложений, то скорее всего у вас возникнет потребность использовать один и тот же код в разных проектах.

    В этой статье приведена пошаговая инструкция по созданию простого Metro style компонента, а также особенности регистрации такой библиотеки для дальнейшего использования в WinRT проектах.

    В качестве примера компонента мы выбрали анимированный индикатор загрузки в стиле Metro, похожий на тот, который многие из нас уже видели в новой версии Windows. К концу этой статьи вы будете не только знать всё о регистрации компонентов, но и иметь возможность добавить готовый индикатор загрузки в своё Metro приложение.


    Системные требования


    Если вы ещё не успели написать свою первую программу для Windows 8, то удостоверьтесь, что ваша среда разработки удовлетворяет следующим требованиям:

    • Разработка должна вестись в операционной системе Windows 8. На момент написания этой статьи Windows 8 доступна в стадии Release Preview и её можно скачать по этой ссылке:
      http://windows.microsoft.com/ru-RU/windows-8/download
    • Для разработки вам понадобится среда разработки Visual Studio 2012, которая на данный момент находится в стадии Release Candidate и доступна для скачивания с http://www.microsoft.com/visualstudio/11/ru-ru/downloads.
      Если у вас нет возможности использовать профессиональную версию Visual Studio, вы всегда можете бесплатно установить себе Visual Studio Express 2012 for Windows 8. В этой статье все действия будут приводиться для интерфейса профессиональной версии Visual Studio 2012.


    Создание библиотеки


    Итак, мы запустили Visual Studio 2012 и готовы сделать свой первый Metro-style компонент.
    Для этого создадим новый проект типа Class Library (Metro style apps) и назовём его MyCustomControls:



    В результате будет создан пустой проект с одним классом. Так как в нашем случае этот класс не понадобится, удалим файл Class1.cs из проекта:



    Затем добавим заготовку для нашего будущего компонента. Для этого в диалоге Add New Item выбираем новый шаблон – Templated Control – и задаем ему имя MyCustomControl:



    После этих действий в проекте появится два новых файла:

    • MyCustomControl.cs, содержащий определение нашего компонента как наследника от контрола:

      namespace MyCustomControls {
          public sealed class MyCustomControl : Control {
              public MyCustomControl() {
                  this.DefaultStyleKey = typeof(MyCustomControl);
              }
          }
      }
      

      Заменим его на код, представленный ниже:

      namespace MyCustomControls {
         public sealed class MyCustomControl : Control {
              const double radius = 30;
      
              public static readonly DependencyProperty DataProperty =
                     DependencyProperty.Register("Data", typeof(Geometry), typeof(MyCustomControl), 
                         new PropertyMetadata(null));
      
              public Geometry Data {
                  get { return (Geometry)GetValue(DataProperty); }
                  set { SetValue(DataProperty, value); }
              }
      
              DispatcherTimer timer;
              double progress = 0.0;
              Size arrangeSize = new Size(0, 0);
              DateTime lastTime = DateTime.Now;
      
              public MyCustomControl() {
                  this.DefaultStyleKey = typeof(MyCustomControl);
                  timer = new DispatcherTimer();
                  timer.Tick += timer_Tick;
                  timer.Interval = TimeSpan.FromMilliseconds(5);
                  timer.Start();
              }
              void timer_Tick(object sender, object e) {
                  DateTime time = DateTime.Now;
                  progress += 0.5 * (time - lastTime).TotalSeconds;
                  lastTime = time;
                  if (progress > 1)
                      progress -= 1;
                  Data = CreateGeometry(progress);
              }
              double CalcAngle(double progress) {
                  double factor = 0.5 * Math.Cos(Math.PI * progress - Math.PI) + 0.5;
                  return 2 * Math.PI * factor;
              }
              double CalcDistance(double angle) {
                  return 0.3 * (Math.PI - Math.Abs(Math.PI - angle));
              }
              Geometry CreateGeometry(double progress) {
                  double angle = CalcAngle(progress);
                  double distance = CalcDistance(angle);
                  GeometryGroup newGeometry = new GeometryGroup() { FillRule = FillRule.Nonzero };
                  for (int i = 3; i > -4; i--) {
                      Point location = 
                          new Point(0.5 * arrangeSize.Width 
                                               + radius * Math.Cos(angle + i * distance - Math.PI / 2),
                                    0.5 * arrangeSize.Height 
                                               + radius * Math.Sin(angle + i * distance - Math.PI / 2));
                          newGeometry.Children.Add(new EllipseGeometry() { 
                                    Center = location, RadiusX = 5, RadiusY = 5 });
                  }
                  return newGeometry;
              }
              protected override Size MeasureOverride(Size availableSize) {
                  base.MeasureOverride(availableSize);
                  return new Size(!double.IsInfinity(availableSize.Width) ? availableSize.Width : 0,
                      !double.IsInfinity(availableSize.Height) ? availableSize.Height : 0);
              }
              protected override Size ArrangeOverride(Size arrangeBounds) {
                  arrangeSize = arrangeBounds;
                  return base.ArrangeOverride(arrangeBounds);
              }
          }
      }

    • Themes\Generic.xaml, где находится описание стиля, который будет применен по умолчанию к нашему контролу. Впишем в разметку элемент Path:

      <ResourceDictionary
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          xmlns:local="using:MyCustomControls">
      
          <Style TargetType="local:MyCustomControl">
              <Setter Property="Template">
                  <Setter.Value>
                      <ControlTemplate TargetType="local:MyCustomControl">
                          <Border
                              Background="{TemplateBinding Background}"
                              BorderBrush="{TemplateBinding BorderBrush}"
                              BorderThickness="{TemplateBinding BorderThickness}">
                              <Path Fill="Aqua" Data="{Binding Path=Data, 
                                    RelativeSource={RelativeSource TemplatedParent} }"/>
                          </Border>
                      </ControlTemplate>
                  </Setter.Value>
              </Setter>
          </Style>
      </ResourceDictionary>
      


    Дальше можно быстро протестировать работу написанного компонента. Для этого добавим еще один проект типа Blank App (XAML):



    Теперь к этому проекту добавим ссылку (типа Project Reference) на нашу сборку MyCustomControls:



    Далее необходимо изменить содержимое файла MainPage.xaml, как показано ниже:

    <Page
        x:Class="App1.MainPage"
        IsTabStop="false"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:App1"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:my="using:MyCustomControls"
        mc:Ignorable="d">
    
        <Grid Background="White">
            <my:MyCustomControl />
        </Grid>
    </Page>
    

    Затем сделаем стартовым приложение App1:



    Теперь запускаем наш проект и видим индикатор загрузки в стиле Metro – а это значит, что наш компонент работоспособен!



    Создание Extension SDK


    Теперь можно перейти непосредственно к созданию собственного Extension SDK. С помощью Extension SDK можно объединить несколько библиотек в один набор, который можно будет подключить в проект Visual Studio, добавив одну ссылку на весь SDK сразу.

    Для начала создадим на жестком диске следующую структуру каталогов, которая будет содержать всё необходимое для нашего SDK:
    MySDK
    — — 1.0
    — — — — References\CommonConfiguration\neutral\MyCustomControls.dll
    — — — — Redist\CommonConfiguration\neutral\MyCustomControls.pri
    — — — — Redist\CommonConfiguration\neutral\MyCustomControls\Themes\generic.xaml
    — — — — SDKManifest.xml

    В этой структуре MySDK – это корневая папка, содержащая все остальные файлы SDK. Она может иметь любое имя, которое отражает название вашего SDK. 1.0 – это версия вашего SDK.

    Директория References должна содержать все модули, которые будут входить в SDK, собранные в соответствующей конфигурации и под определенную архитектуру. То есть следующий уровень определяет конфигурацию, и возможно всего три варианта: Debug, Retail и CommonConfiguration. Последний уровень, соответственно, говорит о том, для какой архитектуры были собраны данные модули: neutral, х64, х86 и ARM. В рассматриваемом случае была сделана сборка в Debug или Release под AnyCPU.

    В директории Redist располагаются файлы, которые необходимы для отладки и выполнения, и они будут упакованы в пакет. И опять всё зависит от конфигурации и архитектуры – точно так же, как и для References.

    Файл SDKManifest.xml должен иметь следующее содержимое:

    <?xml version="1.0" encoding="utf-8" ?>
    <FileList DisplayName="My Custom Controls" ProductFamilyName="My Controls" MinVSVersion="11.0" MinToolsVersion="4.0" CopyRedistToSubDirectory="." AppliesTo="WindowsAppContainer+WindowsXAML+Managed">
    <File Reference="MyCustomControls.dll">
    	<ContainsControls>True</ContainsControls>
    </File>
    </FileList>
    

    Этот файл описывает все сборки, которые находятся в папке References. Параметр CopyRedistToSubDirectory задает, куда будут скопированы файлы из папки Redist относительно корня пакета. Мы установили его как "." – это означает, что все файлы будут скопированы в корень пакета.

    Регистрация Extension SDK


    Теперь вы можете зарегистрировать ваш SDK одним из следующих способов:

    • скопировать папку MySDK в папку "%ProgramFiles%\Microsoft SDKs\Windows\v8.0\Extension SDKs\"
    • добавить ключ в реестр, который будет содержать путь к нашему SDK. Приведу пример *.reg файла, который будет добавлять соответствующие данные в реестр:
      REGEDIT4
      [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v8.0\ExtensionSDKs\MySDK\1.0]
      @="C:\\Sources\\MySDK\\1.0"  
      


    После того, как SDK был создан и зарегистрирован, можно создать новый тестовый проект типа Blank App (XAML).

    При этом мы видим, что при добавлении ссылки на MyCustomControls.dll в разделе Windows-> Extentions будет виден MySDK.



    Чтобы проверить, всё ли работает в этом случае, модифицируем файл MainPage.xaml аналогично тому, как мы делали в предыдущем тестовым примере, затем собираем и запускаем проект – и видим наш индикатор загрузки в действии!

    Полезные ссылки


    Более подробную информацию о том, как создать свой Extension SDK, можно найти по следующий ссылке:
    http://msdn.microsoft.com/library/hh768146(v=VS.110).aspx

    Если вы хотите глубже познакомиться с WinRT, вот ссылки на другие полезные ресурсы:

    Developer Soft

    124,47

    Компания

    Поделиться публикацией

    Похожие публикации

    Комментарии 14
      +5
      теперь это Windows 8-style UI же
      +1
      И чего Microsoft парится? Быстро переименовали бы на какой-нибудь Wetro и всё. Опыт китайцев.
        +1
        Как ведро и назовешь — так оно и полетит
          +5
          Ну тогда Windows Tram UI. Чего выдумывать.
        +3
        Хорошая статья, но к сожалению то, что тут описано не является настоящим «компонентом для WinRT». Это managed control, который можно успешно использовать в C#/VB/XAML приложениях, но не в C++/XAML, HTML/JS и т.п. Настоящий WinRT компонент имеет расширение .winmd, а не .dll и, даже если посмотреть на первый скриншот в статье, можно увидеть пункт следующий за выбраным, который и называется «Windows Runtime Component».

        К сожалению пока не доводилось видеть статей о том, как из .NET котрола сделать полноценный WinRT компонент.
          +3
          Я с Вами согласен, что это не совсем WinRT компонент, но данный подход можно легко применить для создания .winmd библиотеки. И, к сожалению, на данный момент визуальные WinRT компоненты (.winmd) нельзя использовать в проектах HTML/JS.
            +4
            1. Выберите при создании пункт Windows Runtime Component.
            2. Сделайте свойство DataProperty — private.

            Всё — компонент собирается в winmd и добавляется к C++/XAML и HTML/JS проектам.

            Единственное дополнительно отличие «полноценного WinRT компонент» от «просто компонента» — все публично доступные типы должны быть — WinRT.

            Всё максимально прозрачно.
              +1
              Я сам пока не пробовал, но помоему не все там так просто. Иначе не вижу причин почему практически все компоненты на сегодняшний день выпускаются под managed платформу. Да и туториалов подобных этому я видел несколько, но почему-то никто не пишет на примере настоящего WinRT компонента.

              Ну, мне скоро предстоит попробовать этим заняться — там и посмотрим :)
                +4
                Перед тем, как писать — сам проверил.

                Полученный winmd:
                — добавляется в C++/XAML проект — и сразу же работает, как и ожидается
                — добавляется в HTML/JS проект, но как его отобразить — не нашёл, но я не большой специалист в HTML/JS — дождусь RTM — попробую ещё раз
                  0
                  Спасибо. Я так понимаю проблемы возникнут при создании чего-то более сложного. Ну, посмотрим.

          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

          Самое читаемое