【问题标题】:How to get current used color theme of Visual Studio如何获取 Visual Studio 当前使用的颜色主题
【发布时间】:2013-04-10 08:22:09
【问题描述】:

我正在创建自己的 IntelliSense Presenter,因为 Visual Studio2012 支持更改主题,所以我希望我的演示者的背景颜色可以在主题更改时自动更改。有没有办法跟踪主题更改事件,或者获取 Visual Studio 的当前颜色主题?

【问题讨论】:

    标签: visual-studio-2012 intellisense visual-studio-extensions


    【解决方案1】:

    是的,这是可能的。我不得不用我的一个扩展解决一个类似的问题...... 当前主题存储在 Windows 注册表中;所以我实现了以下实用程序类。

    public enum VsTheme
    {
        Unknown = 0, 
        Light, 
        Dark, 
        Blue
    }
    
    public class ThemeUtil
    {
        private static readonly IDictionary<string, VsTheme> Themes = new Dictionary<string, VsTheme>()
        {
            { "de3dbbcd-f642-433c-8353-8f1df4370aba", VsTheme.Light }, 
            { "1ded0138-47ce-435e-84ef-9ec1f439b749", VsTheme.Dark }, 
            { "a4d6a176-b948-4b29-8c66-53c97a1ed7d0", VsTheme.Blue }
        };
    
        public static VsTheme GetCurrentTheme()
        {
            string themeId = GetThemeId();
            if (string.IsNullOrWhiteSpace(themeId) == false)
            {
                VsTheme theme;
                if (Themes.TryGetValue(themeId, out theme))
                {
                    return theme;
                }
            }
    
            return VsTheme.Unknown;
        }
    
        public static string GetThemeId()
        {
            const string CategoryName = "General";
            const string ThemePropertyName = "CurrentTheme";
            string keyName = string.Format(@"Software\Microsoft\VisualStudio\11.0\{0}", CategoryName);
    
            using (RegistryKey key = Registry.CurrentUser.OpenSubKey(keyName))
            {
                if (key != null)
                {
                    return (string)key.GetValue(ThemePropertyName, string.Empty);
                }
            }
    
            return null;
        }
    }
    

    好的;这只是有助于弄清楚当前的设置......听主题更改通知有点棘手。在你的包被加载之后,你必须通过 DTE 获取一个 IVsShell 实例;一旦你有了这个对象,你就可以利用 AdviceBroadcastMessages 方法来订阅事件通知。您必须提供一个类型实现 IVsBroadcastMessageEvents 接口的对象...

    我不想发布整个实现,但以下几行可能说明了关键场景...

    class VsBroadcastMessageEvents : IVsBroadcastMessageEvent
    {
        int IVsBroadcastMessageEvent.OnBroadcastMessage(uint msg, IntPtr wParam, IntPtr lParam)
        {
            const uint WM_SYSCOLORCHANGE = 0x15;
            if (msg == WM_SYSCOLORCHANGE) 
            {
                // obtain current theme from the Registry and update any UI...
            }
        }
    }
    

    考虑在该类型上实现 IDisposable,以便能够在包被卸载时取消订阅事件源。

    这就是我订阅事件通知的方式...

    class ShellService
    {
        private readonly IVsShell shell;
        private bool advised;
    
        public ShellService(IVsShell shellInstance)
        {
            this.shell = shellInstance;
        }
    
        public void AdviseBroadcastMessages(IVsBroadcastMessageEvents broadcastMessageEvents, out uint cookie)
        {
            cookie = 0;
            try
            {
                int r = this.shell.AdviseBroadcastMessages(broadcastMessageEvents, out cookie);
                this.advised = (r == VSConstants.S_OK);
            }
            catch (COMException) { }
            catch (InvalidComObjectException) { }
        }
    
        public void UnadviseBroadcastMessages(uint cookie)
        {
            ...
        }
    }
    

    保持cookie参数的值;您需要它才能成功退订。

    希望有所帮助(-:

    【讨论】:

    • 这很好用,我只是做了一个增强。在 GetThemeId 方法中,keyName 指向特定版本 (11.0)。您也可以替换它以使其适用于多个版本。我使用DTE.Version 属性来获取当前版本,它返回一个字符串并正确格式化以适合
    【解决方案2】:

    只是想进行更新以防万一其他人出现.. @Matze 和 @Frank 完全正确.. 但是在 VS 2015 中.. 他们添加了一种简单的方法来检测主题更改。所以你需要包含 PlatformUI 并且你会得到一个超级简单的事件

    using Microsoft.VisualStudio.PlatformUI;
    ....
     //Then you get an event 
     VSColorTheme.ThemeChanged += VSColorTheme_ThemeChanged;
    

    您应该确保您的控件是一次性的,以便您可以取消订阅该事件...

    奖金!

    它还使您可以轻松访问颜色.. 即使用户已将它们从默认值更改.. 因此您可以在设置颜色时执行类似的操作

    var defaultBackground = VSColorTheme.GetThemedColor(EnvironmentColors.ToolWindowBackgroundColorKey);
    var defaultForeground = VSColorTheme.GetThemedColor(EnvironmentColors.ToolWindowTextColorKey);
    

    【讨论】:

    • 这些行为我提供了相同的深色和浅色主题输出。 var defaultBackground = VSColorTheme.GetThemedColor(EnvironmentColors.ToolWindowBackgroundColorKey); var defaultForeground = VSColorTheme.GetThemedColor(EnvironmentColors.ToolWindowTextColorKey);
    【解决方案3】:

    对于 VS 2015,这已经改变,解决方案 @Matze 仍然有效,但您需要更新 GetThemeId() 函数以检查版本,如果它是 14.0 (VS2015),请在注册表中的不同位置查找。值的存储方式也发生了变化,它仍然是一个字符串,但现在包含由“*”分隔的其他值。主题 guid 是列表中的最后一个值。

    if (version == "14.0")
    {
       string keyName = string.Format(@"Software\Microsoft\VisualStudio\{0}\ApplicationPrivateSettings\Microsoft\VisualStudio", version);
    
       using (RegistryKey key = Registry.CurrentUser.OpenSubKey(keyName))
       {
          if (key != null)
          {
              var keyText = (string)key.GetValue("ColorTheme", string.Empty);
    
                  if (!string.IsNullOrEmpty(keyText))
                  {
                      var keyTextValues = keyText.Split('*');
                      if (keyTextValues.Length > 2)
                      {
                           return keyTextValues[2];
                      }
                  }
          }
       }
    
       return null;
    }
    

    【讨论】:

    • EnvDTE.DTE dte = (EnvDTE.DTE)Package.GetGlobalService(typeof(EnvDTE.DTE));字符串版本 = dte.Version;
    猜你喜欢
    • 1970-01-01
    • 2021-06-05
    • 1970-01-01
    • 2017-01-13
    • 1970-01-01
    • 2014-05-17
    • 2019-03-07
    • 1970-01-01
    • 2013-05-17
    相关资源
    最近更新 更多