VS 2012扩展中的标准控件

8
我现在正在修改一个公司内部的VS插件以支持Visual Studio 2012。我遇到的问题是如何使UI动态地适应活动的VS主题。

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

因此,问题是:是否有可能使VS扩展的WPF工具窗口中的标准控件看起来类似于Visual Studio中使用的控件?我知道我可以使用控件模板或自定义控件自己完成这个任务,但如果可能的话,我真的想避免这样做。


这里的问题是在VS中没有一个通用的控件集。..\Microsoft Visual Studio 11.0\VSSDK\VisualStudioIntegration\Common\Assemblies\v4.0\Microsoft.VisualStudio.Shell.11.0.dll 包含非常少量的控件,即使它们也仅限于在StartPage等位置找到的内容。更广泛的控件集存在于 Microsoft Visual Studio 11.0\Common7\IDE\en\Microsoft.VisualStudio.Shell.UI.Internal.resources.dll 中,但只有其中的一些可以通过DynamicResource引用到您的包项目中。 - Viv
续上。也许最好的方法是查看 Internal.resources.dll 中的样式,并将其复制到您自己的 ResourceDictionary 中,以在所有包项目中使用。这样,即使通过服务包在 VS 中切换了某些内容,您的 UI 也不会被破坏。似乎不能直接获取样式或通过在 *.vsct 文件中指定 xaml 控件是相当糟糕的。 - Viv
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图标一样(带有灰色轮廓,就像这个error icon)。

谢谢Mikhail,我会选择Metro工具包与VsBrushes/VsColors相结合。 - Florian Greinacher

1

Dll decompile

Microsoft.VisualStudio.Shell.12.dll 的资源中有一个 themes/generic.baml,可能包含你正在寻找的控件样式。我使用了 dotPeek,但我没有安装可视化 Baml 文件的插件,你可以尝试一些插件。不过,你应该检查许可证是否允许使用提取的样式 =P。

我已经检查过它们了。这些是一些具体的样式,与一般控件没有太多关系。我尝试使用 SnoopWpf 和 WpfInspector 从运行中的 Visual Studio 中提取它们,但第一个不显示样式的详细信息,而第二个虽然非常棒,但无法检查Visual Studio - 不管是2012还是2013版本。 - Spook
顺便提一下,您可以使用ILSpy将Baml反编译为Xaml。 - Spook

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接