8

我目前正在更改公司内部的 VS 扩展以支持 Visual Studio 2012。我正在苦苦挣扎的是如何使 UI 动态适应活动的 VS 主题。

我找到了几个颜色/画笔的资源键(Microsoft.VisualStudio.Shell.11.0.dll 中的 VsColors/VsBrushes),我可以轻松地使用它们来更改扩展的基本配色方案。问题是标准控件(文本框、组合框、复选框)具有默认的 WPF 外观,看起来很奇怪。

所以问题是:是否有可能使 VS 扩展的 WPF 工具窗口中的标准控件看起来类似于 Visual Studio 中使用的控件?我知道我可以自己使用控件模板或自定义控件来做到这一点,但如果可能的话,我真的想避免这种努力。

4

2 回答 2

7

Visual Studio 2012 使用自定义 WPF 控件。您可以通过Snoop自己验证这一点。Visual Studio 2012 的 WPF 可视化树包含诸如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();
  }
}

要正确反转,Light 主题的图标应该是另一个 Visual Studio 图标(周围有灰色边缘,像这样错误图标)。

于 2013-07-08T09:06:50.577 回答
1

dll反编译

themes/generic.baml资源中有一个Microsoft.VisualStudio.Shell.12.dll可能包含您正在寻找的控件的样式。我使用了 dotPeek,但我没有安装插件来可视化 Baml 文件,您可以尝试一些。

您应该检查许可证是否允许您通过 =P 使用提取的样式。

于 2013-07-08T09:02:04.730 回答