Стандартные элементы управления в расширении VS 2012

В настоящее время я меняю внутреннее расширение VS для поддержки Visual Studio 2012. Я борюсь с тем, как сделать так, чтобы пользовательский интерфейс динамически адаптировался к активной теме VS.

Я нашел несколько ключей ресурсов для цветов/кистей (VsColors/VsBrushes в Microsoft.VisualStudio.Shell.11.0.dll), которые я могу легко использовать для изменения базовой цветовой схемы расширения. Проблема в том, что стандартные элементы управления (текстовые поля, поля со списком, флажки) имеют внешний вид WPF по умолчанию, который выглядит очень странно.

Итак, вопрос: есть ли возможность сделать стандартные элементы управления в окне инструмента WPF расширения VS похожими на те, которые используются в Visual Studio? Я знаю, что мог бы сделать это сам, используя шаблоны элементов управления или пользовательские элементы управления, но я действительно хочу избежать этих усилий, если это возможно.


person Florian Greinacher    schedule 27.06.2013    source источник
comment
Дело в том, что в VS не существует единого общего набора элементов управления. ..\Microsoft Visual Studio 11.0\VSSDK\VisualStudioIntegration\Common\Assemblies\v4.0\Microsoft.VisualStudio.Shell.11.0.dll содержит очень мало элементов управления, и даже они ограничены тем, что вы найдете на стартовой странице и так далее. В Microsoft Visual Studio 11.0\Common7\IDE\en\Microsoft.VisualStudio.Shell.UI.Internal.resources.dll существует гораздо более обширный набор элементов управления, но лишь немногие из них могут быть связаны через DynamicResource с вашим пакетным проектом.   -  person Viv    schedule 09.07.2013
comment
^^ Продолжение. Возможно, было бы лучше взглянуть на стили в Internal.resources.dll и скопировать их в свой собственный ResourceDictionary для использования во всех ваших проектах пакетов. Таким образом, даже если что-то переключится в VS через сервис-пак, ваш пользовательский интерфейс не сломается. Кажется довольно плохим, что нельзя получить стили напрямую или указать элементы управления xaml в файлах *.vsct.   -  person Viv    schedule 09.07.2013


Ответы (2)


Visual Studio 2012 использует настраиваемые элементы управления WPF. Вы можете убедиться в этом самостоятельно с помощью Snoop. Визуальное дерево WPF Visual Studio 2012 содержит такие элементы управления, как Microsoft.VisualStudio.PlatformUI.VsButton, Microsoft.VisualStudio.PlatformUI.Shell.Controls.TabGroupControl, Microsoft.VisualStudio.PlatformUI.SearchControl. К сожалению, эти элементы управления не документированы, и их сложно или невозможно использовать повторно. Вы можете только просматривать стили сложных элементов и реализовывать аналогичные в своем коде.

Я создаю аналогичные элементы управления на основе коллекции Winfried Lötzsch (теперь он включен в инструментарий MahApps.Metro). Я также видел другую коллекцию привлекательных элементов. Это тоже может быть полезно.

Для реализации поддержки тем Visual Studio я использую ресурсы из Microsoft.VisualStudio.Shell.VsBrushes/VsColors и собственные цвета. Чтобы преобразовать значки в текущую тему, я использую следующий код:

private readonly IVsUIShell5 _vsUIShell5;
private string _currentThemeId;

// cache icons for specific themes: <<ThemeId, IconForLightTheme>, IconForThemeId>
private readonly Dictionary<Tuple<string, BitmapImage>, BitmapImage> _cacheThemeIcons = 
  new Dictionary<Tuple<string, BitmapImage>, BitmapImage>();

protected override BitmapImage GetIconCurrentTheme(BitmapImage iconLight)
{
  Debug.Assert(iconLight != null);
  return _currentThemeId.ToThemesEnum() == Themes.Light ? iconLight : GetCachedIcon(iconLight);
}

private BitmapImage GetCachedIcon(BitmapImage iconLight)
{
  BitmapImage cachedIcon;
  var key = Tuple.Create(_currentThemeId, iconLight);
  if (_cacheThemeIcons.TryGetValue(key, out cachedIcon))
  {
    return cachedIcon;
  }

  var backgroundColor = FindResource<Color>(VsColors.ToolWindowBackgroundKey);
  cachedIcon = CreateInvertedIcon(iconLight, backgroundColor);
  _cacheThemeIcons.Add(key, cachedIcon);
  return cachedIcon;
}

private BitmapImage CreateInvertedIcon(BitmapImage inputIcon, Color backgroundColor)
{
  using (var bitmap = inputIcon.ToBitmapByPngEncoder())
  {
    var rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
    var bitmapData = bitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, bitmap.PixelFormat);
    var sourcePointer = bitmapData.Scan0;
    var length = Math.Abs(bitmapData.Stride) * bitmap.Height;
    var outputBytes = new byte[length];
    Marshal.Copy(sourcePointer, outputBytes, 0, length);
    _vsUIShell5.ThemeDIBits((UInt32)outputBytes.Length, outputBytes, (UInt32)bitmap.Width,
                            (UInt32)bitmap.Height, true, backgroundColor.ToUInt());
    Marshal.Copy(outputBytes, 0, sourcePointer, length);
    bitmap.UnlockBits(bitmapData);
    return bitmap.ToPngBitmapImage();
  }
}

Чтобы инвертировать правильно, значок светлой темы должен быть таким же, как другие значки Visual Studio (с серым ободком вокруг, как этот значок ошибки  ).

person Mikhail Shcherbakov    schedule 08.07.2013
comment
Спасибо, Михаил, я выберу инструментарий Metro в сочетании с VsBrushes/VsColors. - person Florian Greinacher; 10.07.2013

Dll декомпилировать

В ресурсах Microsoft.VisualStudio.Shell.12.dll есть themes/generic.baml, который может содержать стили для элементов управления, которые вы ищете. Я использовал dotPeek, но у меня не установлен плагин для визуализации файлов Baml, вы можете попробовать несколько.

Вы должны проверить, позволяет ли лицензия использовать извлеченные стили, хотя =P.

person mikehc    schedule 08.07.2013
comment
Я проверил их. Это некоторые специфические стили, мало связанные с общими элементами управления. Я попытался извлечь их из запущенной Visual Studio с помощью SnoopWpf и WpfInspector, но первый не показывает детали стилей, а второй, хотя и довольно крутой, не может проверять Visual Studio - ни 2012, ни 2013. - person Spook; 21.11.2013
comment
Кстати, вы можете использовать ILSpy для декомпиляции Baml в Xaml. - person Spook; 21.11.2013