Update Control Panel

The Control Panel now also includes third party panel items.
This commit is contained in:
Coenraad Stijne
2014-07-18 20:15:35 +02:00
parent 2a86b06e0c
commit 102d5fdd7f
4 changed files with 221 additions and 157 deletions

View File

@@ -51,9 +51,9 @@ namespace Wox.Plugin.SystemPlugins.ControlPanel
foreach (ControlPanelItem item in controlPanelItems) foreach (ControlPanelItem item in controlPanelItems)
{ {
if (!File.Exists(iconFolder + item.ApplicationName + fileType)) if (!File.Exists(iconFolder + item.LocalizedString + fileType))
{ {
item.Icon.ToBitmap().Save(iconFolder + item.ApplicationName + fileType); item.Icon.ToBitmap().Save(iconFolder + item.LocalizedString + fileType);
} }
} }
} }
@@ -75,7 +75,7 @@ namespace Wox.Plugin.SystemPlugins.ControlPanel
Title = item.LocalizedString, Title = item.LocalizedString,
SubTitle = item.InfoTip, SubTitle = item.InfoTip,
Score = item.Score, Score = item.Score,
IcoPath = "Images\\ControlPanelIcons\\" + item.ApplicationName + fileType, IcoPath = "Images\\ControlPanelIcons\\" + item.LocalizedString + fileType,
Action = e => Action = e =>
{ {
try try

View File

@@ -8,18 +8,16 @@ namespace Wox.Plugin.SystemPlugins.ControlPanel
{ {
public string LocalizedString { get; private set; } public string LocalizedString { get; private set; }
public string InfoTip { get; private set; } public string InfoTip { get; private set; }
public string ApplicationName { get; private set; }
public ProcessStartInfo ExecutablePath { get; private set; } public ProcessStartInfo ExecutablePath { get; private set; }
public Icon Icon { get; private set; } public Icon Icon { get; private set; }
public int Score { get; set; } public int Score { get; set; }
public ControlPanelItem(string newLocalizedString, string newInfoTip, string newApplicationName, ProcessStartInfo newExecutablePath, Icon newLargeIcon) public ControlPanelItem(string newLocalizedString, string newInfoTip, ProcessStartInfo newExecutablePath, Icon newIcon)
{ {
LocalizedString = newLocalizedString; LocalizedString = newLocalizedString;
InfoTip = newInfoTip; InfoTip = newInfoTip;
ApplicationName = newApplicationName;
ExecutablePath = newExecutablePath; ExecutablePath = newExecutablePath;
Icon = (Icon)newLargeIcon.Clone(); Icon = newIcon;
} }
} }
} }

View File

@@ -45,108 +45,193 @@ namespace Wox.Plugin.SystemPlugins.ControlPanel
static Queue<IntPtr> iconQueue; static Queue<IntPtr> iconQueue;
public static List<ControlPanelItem> Create(int iconSize)
static RegistryKey nameSpace = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ControlPanel\\NameSpace");
static RegistryKey clsid = Registry.ClassesRoot.OpenSubKey("CLSID");
public static List<ControlPanelItem> Create(uint iconSize)
{ {
List<ControlPanelItem> controlPanelItems = new List<ControlPanelItem>(); int size = (int)iconSize;
string applicationName; RegistryKey currentKey;
string[] localizedString;
string[] infoTip = new string[1];
List<string> iconString;
IntPtr dataFilePointer;
uint stringTableIndex;
IntPtr iconIndex;
StringBuilder resource;
ProcessStartInfo executablePath; ProcessStartInfo executablePath;
IntPtr iconPtr = IntPtr.Zero; List<ControlPanelItem> controlPanelItems = new List<ControlPanelItem>();
string localizedString;
string infoTip;
Icon myIcon; Icon myIcon;
RegistryKey nameSpace = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ControlPanel\\NameSpace");
RegistryKey clsid = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Classes\\CLSID");
RegistryKey currentKey;
foreach (string key in nameSpace.GetSubKeyNames()) foreach (string key in nameSpace.GetSubKeyNames())
{
//todo:throw exceptions in my computer, need to check this,Silently Fail for now.
try
{ {
currentKey = clsid.OpenSubKey(key); currentKey = clsid.OpenSubKey(key);
if (currentKey != null) if (currentKey != null)
{ {
if (currentKey.GetValue("System.ApplicationName") != null && executablePath = getExecutablePath(currentKey);
currentKey.GetValue("LocalizedString") != null)
if (executablePath == null)
continue; //Cannot have item without executable path
localizedString = getLocalizedString(currentKey);
if (string.IsNullOrEmpty(localizedString))
continue; //Cannot have item without Title
infoTip = getInfoTip(currentKey);
myIcon = getIcon(currentKey, size);
controlPanelItems.Add(new ControlPanelItem(localizedString, infoTip, executablePath, myIcon));
}
}
return controlPanelItems;
}
private static ProcessStartInfo getExecutablePath(RegistryKey currentKey)
{ {
ProcessStartInfo executablePath = new ProcessStartInfo();
string applicationName;
if (currentKey.GetValue("System.ApplicationName") != null)
{
//CPL Files (usually native MS items)
applicationName = currentKey.GetValue("System.ApplicationName").ToString(); applicationName = currentKey.GetValue("System.ApplicationName").ToString();
//Debug.WriteLine(key.ToString() + " (" + applicationName + ")"); executablePath.FileName = Environment.ExpandEnvironmentVariables(CONTROL);
localizedString = currentKey.GetValue("LocalizedString") executablePath.Arguments = "-name " + applicationName;
.ToString()
.Split(new char[] {','}, 2);
if (localizedString[0][0] == '@')
{
localizedString[0] = localizedString[0].Substring(1);
} }
localizedString[0] = Environment.ExpandEnvironmentVariables(localizedString[0]); else if (currentKey.OpenSubKey("Shell\\Open\\Command") != null && currentKey.OpenSubKey("Shell\\Open\\Command").GetValue(null) != null)
if (localizedString.Length > 1)
{ {
dataFilePointer = LoadLibraryEx(localizedString[0], IntPtr.Zero, //Other files (usually third party items)
LOAD_LIBRARY_AS_DATAFILE); executablePath.FileName = Environment.ExpandEnvironmentVariables(currentKey.OpenSubKey("Shell\\Open\\Command").GetValue(null).ToString());
stringTableIndex = sanitizeUint(localizedString[1]);
resource = new StringBuilder(255);
LoadString(dataFilePointer, stringTableIndex, resource, resource.Capacity + 1);
localizedString[0] = resource.ToString();
if (currentKey.GetValue("InfoTip") != null)
{
infoTip = currentKey.GetValue("InfoTip").ToString().Split(new char[] {','}, 2);
if (infoTip[0][0] == '@')
{
infoTip[0] = infoTip[0].Substring(1);
}
infoTip[0] = Environment.ExpandEnvironmentVariables(infoTip[0]);
dataFilePointer = LoadLibraryEx(infoTip[0], IntPtr.Zero, LOAD_LIBRARY_AS_DATAFILE);
stringTableIndex = sanitizeUint(infoTip[1]);
resource = new StringBuilder(255);
LoadString(dataFilePointer, stringTableIndex, resource, resource.Capacity + 1);
infoTip[0] = resource.ToString();
}
else if (currentKey.GetValue(null) != null)
{
infoTip[0] = currentKey.GetValue(null).ToString();
} }
else else
{ {
infoTip[0] = ""; return null;
} }
return executablePath;
}
private static string getLocalizedString(RegistryKey currentKey)
{
IntPtr dataFilePointer;
string[] localizedStringRaw;
uint stringTableIndex;
StringBuilder resource;
string localizedString;
if (currentKey.GetValue("LocalizedString") != null)
{
localizedStringRaw = currentKey.GetValue("LocalizedString").ToString().Split(new char[] { ',' }, 2);
if (localizedStringRaw.Length > 1)
{
if (localizedStringRaw[0][0] == '@')
{
localizedStringRaw[0] = localizedStringRaw[0].Substring(1);
}
localizedStringRaw[0] = Environment.ExpandEnvironmentVariables(localizedStringRaw[0]);
dataFilePointer = LoadLibraryEx(localizedStringRaw[0], IntPtr.Zero, LOAD_LIBRARY_AS_DATAFILE); //Load file with strings
stringTableIndex = sanitizeUint(localizedStringRaw[1]);
resource = new StringBuilder(255);
LoadString(dataFilePointer, stringTableIndex, resource, resource.Capacity + 1); //Extract needed string
FreeLibrary(dataFilePointer); FreeLibrary(dataFilePointer);
//We are finished with extracting strings. Prepare to load icon file.
dataFilePointer = IntPtr.Zero; localizedString = resource.ToString();
myIcon = null;
iconPtr = IntPtr.Zero; /*This shouldn't be necessary, but some apps (e.g. Bootcamp)
* don't follow Microsoft's standard. Have to make a choice whether
* empty string == failure, or use default name. I'm using default name */
if (String.IsNullOrEmpty(localizedString))
{
if (currentKey.GetValue(null) != null)
{
localizedString = currentKey.GetValue(null).ToString();
}
else
{
return null; //Cannot have item without title.
}
}
}
else
{
localizedString = localizedStringRaw[0];
}
}
else if (currentKey.GetValue(null) != null)
{
localizedString = currentKey.GetValue(null).ToString();
}
else
{
return null; //Cannot have item without title.
}
return localizedString;
}
private static string getInfoTip(RegistryKey currentKey)
{
IntPtr dataFilePointer;
string[] infoTipRaw;
uint stringTableIndex;
StringBuilder resource;
string infoTip = "";
if (currentKey.GetValue("InfoTip") != null)
{
infoTipRaw = currentKey.GetValue("InfoTip").ToString().Split(new char[] { ',' }, 2);
if (infoTipRaw.Length == 2)
{
if (infoTipRaw[0][0] == '@')
{
infoTipRaw[0] = infoTipRaw[0].Substring(1);
}
infoTipRaw[0] = Environment.ExpandEnvironmentVariables(infoTipRaw[0]);
dataFilePointer = LoadLibraryEx(infoTipRaw[0], IntPtr.Zero, LOAD_LIBRARY_AS_DATAFILE); //Load file with strings
stringTableIndex = sanitizeUint(infoTipRaw[1]);
resource = new StringBuilder(255);
LoadString(dataFilePointer, stringTableIndex, resource, resource.Capacity + 1); //Extract needed string
FreeLibrary(dataFilePointer);
infoTip = resource.ToString();
}
}
else
{
infoTip = "";
}
return infoTip;
}
private static Icon getIcon(RegistryKey currentKey, int iconSize)
{
IntPtr iconPtr = IntPtr.Zero;
List<string> iconString;
IntPtr dataFilePointer;
IntPtr iconIndex;
Icon myIcon = null;
if (currentKey.OpenSubKey("DefaultIcon") != null) if (currentKey.OpenSubKey("DefaultIcon") != null)
{ {
if (currentKey.OpenSubKey("DefaultIcon").GetValue(null) != null) if (currentKey.OpenSubKey("DefaultIcon").GetValue(null) != null)
{ {
iconString = iconString = new List<string>(currentKey.OpenSubKey("DefaultIcon").GetValue(null).ToString().Split(new char[] { ',' }, 2));
new List<string>(
currentKey.OpenSubKey("DefaultIcon")
.GetValue(null)
.ToString()
.Split(new char[] {','}, 2));
if (iconString[0][0] == '@') if (iconString[0][0] == '@')
{ {
iconString[0] = iconString[0].Substring(1); iconString[0] = iconString[0].Substring(1);
} }
dataFilePointer = LoadLibraryEx(iconString[0], IntPtr.Zero, dataFilePointer = LoadLibraryEx(iconString[0], IntPtr.Zero, LOAD_LIBRARY_AS_DATAFILE);
LOAD_LIBRARY_AS_DATAFILE);
if (iconString.Count < 2) if (iconString.Count < 2)
{ {
@@ -159,56 +244,37 @@ namespace Wox.Plugin.SystemPlugins.ControlPanel
if (iconIndex == IntPtr.Zero) if (iconIndex == IntPtr.Zero)
{ {
iconQueue = new Queue<IntPtr>(); iconQueue = new Queue<IntPtr>();
EnumResourceNamesWithID(dataFilePointer, GROUP_ICON, EnumResourceNamesWithID(dataFilePointer, GROUP_ICON, new EnumResNameDelegate(EnumRes), IntPtr.Zero); //Iterate through resources.
new EnumResNameDelegate(EnumRes), IntPtr.Zero);
//Iterate through resources.
while (iconPtr == IntPtr.Zero && iconQueue.Count > 0) while (iconPtr == IntPtr.Zero && iconQueue.Count > 0)
{ {
iconPtr = LoadImage(dataFilePointer, iconQueue.Dequeue(), 1, iconSize, iconPtr = LoadImage(dataFilePointer, iconQueue.Dequeue(), 1, iconSize, iconSize, 0);
iconSize, 0);
} }
} }
else else
{ {
iconPtr = LoadImage(dataFilePointer, iconIndex, 1, iconSize, iconSize, 0); iconPtr = LoadImage(dataFilePointer, iconIndex, 1, iconSize, iconSize, 0);
} }
FreeLibrary(dataFilePointer);
try try
{ {
myIcon = Icon.FromHandle(iconPtr); myIcon = Icon.FromHandle(iconPtr);
myIcon = (Icon)myIcon.Clone(); //Remove pointer dependancy.
} }
catch (Exception) catch
{ {
//Silently fail for now. //Silently fail for now..
} }
} }
} }
executablePath = new ProcessStartInfo();
executablePath.FileName = Environment.ExpandEnvironmentVariables(CONTROL);
executablePath.Arguments = "-name " + applicationName;
controlPanelItems.Add(new ControlPanelItem(localizedString[0], infoTip[0],
applicationName, executablePath, myIcon));
FreeLibrary(dataFilePointer);
if (iconPtr != IntPtr.Zero) if (iconPtr != IntPtr.Zero)
{ {
DestroyIcon(myIcon.Handle); DestroyIcon(iconPtr);
} }
} return myIcon;
}
}
}
catch (Exception e)
{
Debug.Write(e);
}
}
return controlPanelItems;
} }
private static uint sanitizeUint(string args) //Remove all chars before and after first set of digits. private static uint sanitizeUint(string args) //Remove all chars before and after first set of digits.
@@ -241,12 +307,14 @@ namespace Wox.Plugin.SystemPlugins.ControlPanel
return false; return false;
return true; return true;
} }
private static uint GET_RESOURCE_ID(IntPtr value) private static uint GET_RESOURCE_ID(IntPtr value)
{ {
if (IS_INTRESOURCE(value) == true) if (IS_INTRESOURCE(value) == true)
return (uint)value; return (uint)value;
throw new System.NotSupportedException("value is not an ID!"); throw new System.NotSupportedException("value is not an ID!");
} }
private static string GET_RESOURCE_NAME(IntPtr value) private static string GET_RESOURCE_NAME(IntPtr value)
{ {
if (IS_INTRESOURCE(value) == true) if (IS_INTRESOURCE(value) == true)

View File

@@ -1,8 +1,6 @@
 
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013 # Visual Studio 2012
VisualStudioVersion = 12.0.30110.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wox.Test", "Wox.Test\Wox.Test.csproj", "{FF742965-9A80-41A5-B042-D6C7D3A21708}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wox.Test", "Wox.Test\Wox.Test.csproj", "{FF742965-9A80-41A5-B042-D6C7D3A21708}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wox.Plugin", "Wox.Plugin\Wox.Plugin.csproj", "{8451ECDD-2EA4-4966-BB0A-7BBC40138E80}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wox.Plugin", "Wox.Plugin\Wox.Plugin.csproj", "{8451ECDD-2EA4-4966-BB0A-7BBC40138E80}"