C# Visual Studio Excel 加载项:如何检测 Excel Office 主题更改?
C# Visual Studio Excel Add-in: How can I detect Excel Office Theme Change?
我写了一个 class 来检测当前的 Excel 主题。
获取Excel当前办公主题:
//Declaration
string officeVersion;
int themeCode;
// Get Office Version first
officeVersion = "16.0";
// Goto the Registry Current Version
RegistryKey rk = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Office\" + officeVersion + @"\Common");
// Get Stored Theme
themeCode = (int)rk.GetValue("UI Theme", GlobalVar.COLORFUL);
然后根据themeCode
的值,判断当前Excel的主题是什么:
// Theme Constants
public const int COLORFUL = 0;
public const int DARKGREY = 3;
public const int BLACK = 4;
public const int WHITE = 5;
我的问题:
- How can I detect when the user, during Excel Running, change the Office Theme from the Excel Options?
- In Another way, is there any Excel Event triggered when the User has edited anything from the Excel Options?
- How can I detect/trap that event please?
I used already Process Monitor and got the location of the Registry key where the theme is stored. But I cannot constantly check the Registry, I prefer to detect when the user clicked on More Commmand\Excel Options if that event is detectable.
非常欢迎您的回答和建议。提前致谢!
非常感谢@PortlandRunner 在评论中给我的方法。我想出了以下代码:
using Microsoft.Win32;
using System;
using System.Drawing;
using System.Management;
using System.Security.Principal;
namespace YourProject
{
/*
#####################################
# GLOBAL CONSTANTS FOR OFFICE THEME #
# By Tsiriniaina Rakotonirina #
#####################################
*/
public class GlobalVar
{
//Theme Constants
public const int COLORFUL = 0;
public const int DARKGREY = 3;
public const int BLACK = 4;
public const int WHITE = 5;
}
/*
########################################
# OFFICE CLASS TO RETURN TO THE ADDINS #
# By Tsiriniaina Rakotonirina #
########################################
*/
public class ExcelTheme
{
private int code; //Theme Code
private Color backgroundColor;//Addins Backcolor based on Theme
private Color textForeColor; //Addins Text Color based on Theme
public Color BackgroundColor { get => backgroundColor; set => backgroundColor = value; }
public Color TextForeColor { get => textForeColor; set => textForeColor = value; }
public int Code { get => code; set => code = value; }
}
/*
###############################
# OFFICE THEME CHANGE WATCHER #
# By Tsiriniaina Rakotonirina #
###############################
*/
class ExcelThemeWatcher
{
/*
*****************************************
* CLASS CONSTRUCTOR *
* ---> The Watch start right away after *
* the class is created *
*****************************************
*/
public ExcelThemeWatcher()
{
//Start Watching Office Theme Change
//By calling the following method
StartThemeWatcher();
}
/*
*****************************************
* GET OFFICE VERSION *
* ---> Read the Registry and *
* get the Current Office Version *
*****************************************
*/
public int GetOfficeVersion()
{
//Get Current Excel Version
try
{
//Get Office Version
//Goto the Registry Current Version
RegistryKey rk = Registry.ClassesRoot.OpenSubKey(@"Excel.Application\CurVer");
//Read Current Version
string officeVersion = rk.GetValue("").ToString();
//Office Version
string officeNumberVersion = officeVersion.Split('.')[officeVersion.Split('.').GetUpperBound(0)];
//Return Office Version
return Int32.Parse(officeNumberVersion);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return 0;
}
}
/*
*****************************************
* GET OFFICE THEME *
* ---> Read the Registry and *
* get the Current Office Theme *
*****************************************
*/
private int GetRegistryOfficeTheme()
{
//Get Office Version first
string officeVersion = GetOfficeVersion().ToString("F1");
//Goto the Registry Current Version
RegistryKey rk = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Office\" + officeVersion + @"\Common");
return Convert.ToInt32(rk.GetValue("UI Theme", GlobalVar.COLORFUL));
}
/*
*****************************************
* GET ADDINS THEME *
* ---> Based on the Office Theme *
* Return the Addins Theme *
*****************************************
*/
public ExcelTheme GetAddinsTheme()
{
ExcelTheme theme = new ExcelTheme();
//Default Theme Code
theme.Code = GetRegistryOfficeTheme();
//Get Background Colors
theme.BackgroundColor = ColorTranslator.FromHtml("#EFE9D7");
theme.TextForeColor = ColorTranslator.FromHtml("#004B8D");
try
{
switch (theme.Code)
{
case GlobalVar.COLORFUL:
theme.BackgroundColor = ColorTranslator.FromHtml("#E6E6E6");
theme.TextForeColor = ColorTranslator.FromHtml("#004B8D");
break;
case GlobalVar.DARKGREY:
theme.BackgroundColor = ColorTranslator.FromHtml("#666666");
theme.TextForeColor = ColorTranslator.FromHtml("White");
break;
case GlobalVar.BLACK:
theme.BackgroundColor = ColorTranslator.FromHtml("#323130");
theme.TextForeColor = ColorTranslator.FromHtml("#CCA03B");
break;
case GlobalVar.WHITE:
theme.BackgroundColor = ColorTranslator.FromHtml("#FFFFFF");
theme.TextForeColor = ColorTranslator.FromHtml("#004B8D");
break;
default:
break;
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return theme;
}
/*
******************************************
* START OFFICE THEME CHANGE WATCH *
* ---> Using WMI, read and watch *
* Registry Section for Office Theme *
******************************************
*/
private void StartThemeWatcher()
{
string keyPath; //Office Theme Path
string valueName; //Office Theme Value name
//Get Office Version first
string officeVersion = GetOfficeVersion().ToString("F1");
//Set the KeyPath based on the Office Version
keyPath = @"Software\Microsoft\Office\" + officeVersion + "\Common";
valueName = "UI Theme";
//Get the Current User ID
//---> HKEY_CURRENT_USER doesn't contain Value as it is a shortcut of HKEY_USERS + User ID
// That is why we get that currentUser ID and use it to read the wanted location
//Get the User ID
var currentUser = WindowsIdentity.GetCurrent();
//Build the Query based on 3 parameters
//Param #1: User ID
//Param #2: Location or Path of the Registry Key
//Param #3: Registry Value to watch
var query = new WqlEventQuery(string.Format(
"SELECT * FROM RegistryValueChangeEvent WHERE Hive='HKEY_USERS' AND KeyPath='{0}\\{1}' AND ValueName='{2}'",
currentUser.User.Value, keyPath.Replace("\", "\\"), valueName));
//Create a Watcher based on the "query" we just built
ManagementEventWatcher watcher = new ManagementEventWatcher(query);
//Create the Event using the "Function" to fire up, here called "KeyValueChanged"
watcher.EventArrived += (sender, args) => KeyValueChanged();
//Start the Watcher
watcher.Start();
}
/*
******************************************
* EVENT FIRED UP WHEN CHANGE OCCURS *
* ---> Here the event is instructed *
* to update the Addins Theme *
******************************************
*/
private void KeyValueChanged()
{
// Here, whenever the user change the Office theme,
// this function will automatically Update the Addins Theme
Globals.ThisAddIn.SetAddinsInterfaceTheme();
}
}
}
我觉得没有必要停止观察者,但如果你想出了这个主意,请告诉我把它放在哪里;)
更新:
也很高兴告诉您,当我测试更改 Office 主题并看到我的 Addins 主题也发生变化时,我是如此的存在。也很想听听您的意见!
我写了一个 class 来检测当前的 Excel 主题。
获取Excel当前办公主题:
//Declaration
string officeVersion;
int themeCode;
// Get Office Version first
officeVersion = "16.0";
// Goto the Registry Current Version
RegistryKey rk = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Office\" + officeVersion + @"\Common");
// Get Stored Theme
themeCode = (int)rk.GetValue("UI Theme", GlobalVar.COLORFUL);
然后根据themeCode
的值,判断当前Excel的主题是什么:
// Theme Constants
public const int COLORFUL = 0;
public const int DARKGREY = 3;
public const int BLACK = 4;
public const int WHITE = 5;
我的问题:
- How can I detect when the user, during Excel Running, change the Office Theme from the Excel Options?
- In Another way, is there any Excel Event triggered when the User has edited anything from the Excel Options?
- How can I detect/trap that event please?
I used already Process Monitor and got the location of the Registry key where the theme is stored. But I cannot constantly check the Registry, I prefer to detect when the user clicked on More Commmand\Excel Options if that event is detectable.
非常欢迎您的回答和建议。提前致谢!
非常感谢@PortlandRunner 在评论中给我的方法。我想出了以下代码:
using Microsoft.Win32;
using System;
using System.Drawing;
using System.Management;
using System.Security.Principal;
namespace YourProject
{
/*
#####################################
# GLOBAL CONSTANTS FOR OFFICE THEME #
# By Tsiriniaina Rakotonirina #
#####################################
*/
public class GlobalVar
{
//Theme Constants
public const int COLORFUL = 0;
public const int DARKGREY = 3;
public const int BLACK = 4;
public const int WHITE = 5;
}
/*
########################################
# OFFICE CLASS TO RETURN TO THE ADDINS #
# By Tsiriniaina Rakotonirina #
########################################
*/
public class ExcelTheme
{
private int code; //Theme Code
private Color backgroundColor;//Addins Backcolor based on Theme
private Color textForeColor; //Addins Text Color based on Theme
public Color BackgroundColor { get => backgroundColor; set => backgroundColor = value; }
public Color TextForeColor { get => textForeColor; set => textForeColor = value; }
public int Code { get => code; set => code = value; }
}
/*
###############################
# OFFICE THEME CHANGE WATCHER #
# By Tsiriniaina Rakotonirina #
###############################
*/
class ExcelThemeWatcher
{
/*
*****************************************
* CLASS CONSTRUCTOR *
* ---> The Watch start right away after *
* the class is created *
*****************************************
*/
public ExcelThemeWatcher()
{
//Start Watching Office Theme Change
//By calling the following method
StartThemeWatcher();
}
/*
*****************************************
* GET OFFICE VERSION *
* ---> Read the Registry and *
* get the Current Office Version *
*****************************************
*/
public int GetOfficeVersion()
{
//Get Current Excel Version
try
{
//Get Office Version
//Goto the Registry Current Version
RegistryKey rk = Registry.ClassesRoot.OpenSubKey(@"Excel.Application\CurVer");
//Read Current Version
string officeVersion = rk.GetValue("").ToString();
//Office Version
string officeNumberVersion = officeVersion.Split('.')[officeVersion.Split('.').GetUpperBound(0)];
//Return Office Version
return Int32.Parse(officeNumberVersion);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return 0;
}
}
/*
*****************************************
* GET OFFICE THEME *
* ---> Read the Registry and *
* get the Current Office Theme *
*****************************************
*/
private int GetRegistryOfficeTheme()
{
//Get Office Version first
string officeVersion = GetOfficeVersion().ToString("F1");
//Goto the Registry Current Version
RegistryKey rk = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Office\" + officeVersion + @"\Common");
return Convert.ToInt32(rk.GetValue("UI Theme", GlobalVar.COLORFUL));
}
/*
*****************************************
* GET ADDINS THEME *
* ---> Based on the Office Theme *
* Return the Addins Theme *
*****************************************
*/
public ExcelTheme GetAddinsTheme()
{
ExcelTheme theme = new ExcelTheme();
//Default Theme Code
theme.Code = GetRegistryOfficeTheme();
//Get Background Colors
theme.BackgroundColor = ColorTranslator.FromHtml("#EFE9D7");
theme.TextForeColor = ColorTranslator.FromHtml("#004B8D");
try
{
switch (theme.Code)
{
case GlobalVar.COLORFUL:
theme.BackgroundColor = ColorTranslator.FromHtml("#E6E6E6");
theme.TextForeColor = ColorTranslator.FromHtml("#004B8D");
break;
case GlobalVar.DARKGREY:
theme.BackgroundColor = ColorTranslator.FromHtml("#666666");
theme.TextForeColor = ColorTranslator.FromHtml("White");
break;
case GlobalVar.BLACK:
theme.BackgroundColor = ColorTranslator.FromHtml("#323130");
theme.TextForeColor = ColorTranslator.FromHtml("#CCA03B");
break;
case GlobalVar.WHITE:
theme.BackgroundColor = ColorTranslator.FromHtml("#FFFFFF");
theme.TextForeColor = ColorTranslator.FromHtml("#004B8D");
break;
default:
break;
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return theme;
}
/*
******************************************
* START OFFICE THEME CHANGE WATCH *
* ---> Using WMI, read and watch *
* Registry Section for Office Theme *
******************************************
*/
private void StartThemeWatcher()
{
string keyPath; //Office Theme Path
string valueName; //Office Theme Value name
//Get Office Version first
string officeVersion = GetOfficeVersion().ToString("F1");
//Set the KeyPath based on the Office Version
keyPath = @"Software\Microsoft\Office\" + officeVersion + "\Common";
valueName = "UI Theme";
//Get the Current User ID
//---> HKEY_CURRENT_USER doesn't contain Value as it is a shortcut of HKEY_USERS + User ID
// That is why we get that currentUser ID and use it to read the wanted location
//Get the User ID
var currentUser = WindowsIdentity.GetCurrent();
//Build the Query based on 3 parameters
//Param #1: User ID
//Param #2: Location or Path of the Registry Key
//Param #3: Registry Value to watch
var query = new WqlEventQuery(string.Format(
"SELECT * FROM RegistryValueChangeEvent WHERE Hive='HKEY_USERS' AND KeyPath='{0}\\{1}' AND ValueName='{2}'",
currentUser.User.Value, keyPath.Replace("\", "\\"), valueName));
//Create a Watcher based on the "query" we just built
ManagementEventWatcher watcher = new ManagementEventWatcher(query);
//Create the Event using the "Function" to fire up, here called "KeyValueChanged"
watcher.EventArrived += (sender, args) => KeyValueChanged();
//Start the Watcher
watcher.Start();
}
/*
******************************************
* EVENT FIRED UP WHEN CHANGE OCCURS *
* ---> Here the event is instructed *
* to update the Addins Theme *
******************************************
*/
private void KeyValueChanged()
{
// Here, whenever the user change the Office theme,
// this function will automatically Update the Addins Theme
Globals.ThisAddIn.SetAddinsInterfaceTheme();
}
}
}
我觉得没有必要停止观察者,但如果你想出了这个主意,请告诉我把它放在哪里;)
更新:
也很高兴告诉您,当我测试更改 Office 主题并看到我的 Addins 主题也发生变化时,我是如此的存在。也很想听听您的意见!