Standard controls in VS 2012 extension
Asked Answered
C

2

8

I am currently changing a company-internal VS extension to support Visual Studio 2012. What I am struggling with is how to make the UI adapting to the active VS theme dynamically.

I found several resource keys for colors/brushes (VsColors/VsBrushes in Microsoft.VisualStudio.Shell.11.0.dll) that I can easily use to change the basic color scheme of the extension. The problem is that the standard controls (text boxes, combo boxes, check boxes) have the default WPF appearance which looks really weird.

So the question is: Is there any possibility to make standard controls in a WPF tool window of a VS extension look similar to the ones used in Visual Studio? I am aware that I could do this myself using control templates or custom controls but I really want to avoid this effort if somehow possible.

Capsular answered 27/6, 2013 at 14:15 Comment(2)
Thing here is there isn't one common set of control's used across VS. The ..\Microsoft Visual Studio 11.0\VSSDK\VisualStudioIntegration\Common\Assemblies\v4.0\Microsoft.VisualStudio.Shell.11.0.dll contains very few control's and even they are limited to stuff you find in the StartPage and so on. A much more extensive set of controls exist in Microsoft Visual Studio 11.0\Common7\IDE\en\Microsoft.VisualStudio.Shell.UI.Internal.resources.dll but only few from them can be be referenced via DynamicResource to your package project.Imitable
^^ Cont'd. It might just be better to look at the styles in the Internal.resources.dll and copy it out into your own ResourceDictionary for use in all your package projects. That way even if something is switched in VS via a service-pack, your UI ain't going to get broken. It does seem pretty poor to not be able to get the Style's directly or by specifying xaml control's in the` *.vsct` files.Imitable
I
7

Visual Studio 2012 use custom WPF controls. You can verify this yourself by Snoop. WPF visual tree of Visual Studio 2012 contains such controls as Microsoft.VisualStudio.PlatformUI.VsButton, Microsoft.VisualStudio.PlatformUI.Shell.Controls.TabGroupControl, Microsoft.VisualStudio.PlatformUI.SearchControl. Unfortunately, these controls are not documented and are difficult or impossible to reuse. You can only view styles of complex elements and implement similar in your code.

I create similar controls base on Winfried Lötzsch collection (now it is included in the MahApps.Metro toolkit). I also saw another collection of attractive elements. It may be useful too.

To implement support for Visual Studio themes, I use resources from Microsoft.VisualStudio.Shell.VsBrushes/VsColors and own colors. To convert icons to current theme, I use following code:

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();
  }
}

To inverted correctly, the icon of Light theme should be as another Visual Studio icons (with gray rim around, like this error icon).

Incept answered 8/7, 2013 at 9:6 Comment(1)
Thank you Mikhail, I will go for the Metro toolkit combined with VsBrushes/VsColors.Capsular
M
1

Dll decompile

There is a themes/generic.baml in the resources of Microsoft.VisualStudio.Shell.12.dll that might contain the styles for the controls you are looking for. I used dotPeek but I don't have a plugin installed to visualize the Baml files, there a few you can try.

You should check if the license allows you to use the extracted styles though =P.

Mountainside answered 8/7, 2013 at 9:2 Comment(2)
I checked them out. These are some specific styles, not much related to general controls. I tried to extract them from running Visual Studio with SnoopWpf and WpfInspector, but the first one doesn't show details of styles and the second one, though quite awesome, is not able to inspect Visual Studio - neither 2012, nor 2013.Welkin
BTW, you can use ILSpy to decompile Baml to Xaml.Welkin

© 2022 - 2024 — McMap. All rights reserved.