SOLIDWORKS 3D offers users a dark and a light theme.
There is a setting in Windows 10 that automatically turn on or off theme selection in third-party applications. SOLIDWORKS does not use that feature so it’s about time we wrote an article to show how a custom add-in can automatically pick up that Windows setting. First, to turn on or off app theme mode, you need to :
- Type theme in the Windows search bar and pick the first result.
- Click on Colors on the sidebar and you will get this window.

Clicking light or dark under “Choose your default app mode” will switch the theme in your applications. A good example is Google Chrome.
The source code of the add-in is available on our GitHub. It’s made of two classes:
– swAddIn.cs: This is the add-in class.
– WindowsThemeManager.cs : This class listens for registry changes when the default app mode values.
swAddIn.cs
using Microsoft.Win32; using SolidWorks.Interop.sldworks; using SolidWorks.Interop.swconst; using SolidWorks.Interop.swpublished; using System; using System.Runtime.InteropServices; using System.Windows.Forms; namespace WindowsThemeSync { [Guid("36EB446E-E8D2-4F2A-AE07-B45D8DD92694"), ComVisible(true)] public class WindowsThemeSyncAddIn : ISwAddin { #region fields public SldWorks SOLIDWORKS { get; private set; } public int SessionCookie { get; private set; } public static object AddInName { get; private set; } = "Windows 10 App Mode Sync - Blue Byte Systems Inc."; public static object AddInDescription { get; private set; } = "Syncs your SOLIDWORKS theme with Windows 10 default app mode."; #endregion /// <summary> /// This method is called when the add-in is activated in SOLIDWORKS. /// </summary> /// <param name="ThisSW">The this sw.</param> /// <param name="Cookie">The cookie.</param> /// <returns></returns> public bool ConnectToSW(object ThisSW, int Cookie) { try { SOLIDWORKS = ThisSW as SldWorks; SessionCookie = Cookie; SOLIDWORKS.SetAddinCallbackInfo(0, this, SessionCookie); // sync the existing theme from the Windows settings RefreshTheme(); // start watching for theme registry changes WindowsThemeManager.WindowsThemeChanged += WindowsThemeManager_WindowsThemeChanged; WindowsThemeManager.StartWatchingForThemeChanges(); return true; } catch (Exception e) { // in case something goes wrong // this might fail an older Windows OS MessageBox.Show($"Message = {e.Message} Stacktrace: {e.StackTrace}"); return false; } } /// <summary> /// Fired when the Windows default app mode value in the registry changes /// </summary> /// <param name="sender">The sender.</param> /// <param name="e">The e.</param> private void WindowsThemeManager_WindowsThemeChanged(object sender, Theme_e e) { var currentTheme = (swInterfaceBrightnessTheme_e)SOLIDWORKS.GetUserPreferenceIntegerValue((int)swUserPreferenceIntegerValue_e.swSystemColorsBackground); switch (e) { case Theme_e.Light: if (currentTheme != swInterfaceBrightnessTheme_e.swInterfaceBrightnessTheme_Light) SOLIDWORKS.SetUserPreferenceIntegerValue((int)swUserPreferenceIntegerValue_e.swSystemColorsBackground, (int)swInterfaceBrightnessTheme_e.swInterfaceBrightnessTheme_Light); break; case Theme_e.Dark: if (currentTheme != swInterfaceBrightnessTheme_e.swInterfaceBrightnessTheme_Dark) SOLIDWORKS.SetUserPreferenceIntegerValue((int)swUserPreferenceIntegerValue_e.swSystemColorsBackground, (int)swInterfaceBrightnessTheme_e.swInterfaceBrightnessTheme_Dark); break; default: break; } } /// <summary> /// Refreshes the theme. /// </summary> public void RefreshTheme() { var theme = WindowsThemeManager.GetWindowsTheme(); var currentTheme = (swInterfaceBrightnessTheme_e)SOLIDWORKS.GetUserPreferenceIntegerValue((int)swUserPreferenceIntegerValue_e.swSystemColorsBackground); switch (theme) { case Theme_e.Light: if (currentTheme != swInterfaceBrightnessTheme_e.swInterfaceBrightnessTheme_Light) SOLIDWORKS.SetUserPreferenceIntegerValue((int)swUserPreferenceIntegerValue_e.swSystemColorsBackground, (int)swInterfaceBrightnessTheme_e.swInterfaceBrightnessTheme_Light); break; case Theme_e.Dark: if (currentTheme != swInterfaceBrightnessTheme_e.swInterfaceBrightnessTheme_Dark) SOLIDWORKS.SetUserPreferenceIntegerValue((int)swUserPreferenceIntegerValue_e.swSystemColorsBackground, (int)swInterfaceBrightnessTheme_e.swInterfaceBrightnessTheme_Dark); break; default: break; } } /// <summary> /// Gets called when you deativate the add-in in SOLIDWORKS /// </summary> /// <returns></returns> public bool DisconnectFromSW() { try { // stop watch for registry changes WindowsThemeManager.StopWatchingForThemeChanges(); return true; } catch (Exception e) { //todo: log ex return false; } } #region com registration [ComRegisterFunction] private static void RegisterAssembly(Type t) { try { string KeyPath = string.Format(@"SOFTWARE\SolidWorks\AddIns\{0:b}", t.GUID); RegistryKey rk = Registry.LocalMachine.CreateSubKey(KeyPath); rk.SetValue("Title", AddInName); // Title rk.SetValue("Description", AddInDescription); // Description rk.SetValue(null, 1); // startup parameter (loads addin automatically upon SOLIDWORKS startup) } catch (Exception e) { //todo: msgbox ex throw e; } } [ComUnregisterFunction] private static void UnregisterAssembly(Type t) { try { bool Exist = false; string KeyPath = string.Format(@"SOFTWARE\SolidWorks\AddIns\{0:b}", t.GUID); using (RegistryKey Key = Registry.LocalMachine.OpenSubKey(KeyPath)) { if (Key != null) Exist = true; else Exist = false; } if (Exist) Registry.LocalMachine.DeleteSubKeyTree(KeyPath); } catch (Exception e) { //todo: msgbox ex throw e; } } #endregion } }
WindowsThemeManager.cs:
using Microsoft.Win32; using System; using System.Management; using System.Security.Principal; namespace WindowsThemeSync { public enum Theme_e { Undefined, Light, Dark } public class WindowsThemeManager { #region Public Events public static event EventHandler<Theme_e> WindowsThemeChanged; #endregion #region Private Fields private static ManagementEventWatcher watcher; #endregion #region Private Properties #endregion #region Public Properties public static bool IsWatching { get; private set; } = false; #endregion #region Private Constructors private WindowsThemeManager() { } #endregion #region Private Methods private const string RegistryKeyPath = @"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize"; private const string RegistryValueName = "AppsUseLightTheme"; public static Theme_e GetWindowsTheme() { try { var key = Registry.CurrentUser.OpenSubKey(RegistryKeyPath); var registryValueObject = key?.GetValue(RegistryValueName); if (registryValueObject == null) { return Theme_e.Light; } var registryValue = (int)registryValueObject; key.Close(); return registryValue > 0 ? Theme_e.Light : Theme_e.Dark; } catch (Exception) { return Theme_e.Undefined; } } private static void Watcher_EventArrived(object sender, EventArrivedEventArgs e) { try { var ret = GetWindowsTheme(); WindowsThemeChanged?.Invoke(null, ret); } catch (System.Exception) { // needs to add logger here } } #endregion #region Public Methods public static void StartWatchingForThemeChanges() { try { if (IsWatching == true) throw new Exception("Object already watching registry entry"); var currentUser = WindowsIdentity.GetCurrent(); WqlEventQuery query = new WqlEventQuery( "SELECT * FROM RegistryValueChangeEvent WHERE " + "Hive = 'HKEY_USERS' " + $@"AND KeyPath='{currentUser.User.Value}\\Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize' AND ValueName='{RegistryValueName}'"); watcher = new ManagementEventWatcher(query); watcher.EventArrived -= Watcher_EventArrived; watcher.EventArrived += Watcher_EventArrived; watcher.Start(); IsWatching = true; } catch (Exception) { } } public static void StopWatchingForThemeChanges() { if (watcher != null) { watcher.Stop(); watcher.Dispose(); watcher = null; } IsWatching = false; } #endregion } }