It is currently March 28th, 2024, 5:17 pm

Help with reverse engineering a skin

Get help with creating, editing & fixing problems with skins
User avatar
jsmorley
Developer
Posts: 22628
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Help with reverse engineering a skin

Post by jsmorley »

StArL0rd84 wrote:I'm sorry but i don't see how 'Display the full path in the title bar' helps my situation.
I just need the title, which the skin achieves somehow.
I'm fishing for how i might get that title info it into my skin.
looking forward to see what you come up with, with the new plugin Azack :thumbup:
Give this little plugin a try....
ExplorerWindow_1.0.rmskin
(85.86 KiB) Downloaded 29 times
This will search for open Windows File Explorer windows by window "Title". It's only for Explorer windows, not other applications.

You use the plugin as a [&SectionVariable] with the syntax:

[&PluginMeasureName:FindIt([NameOfFolder])]

Quotes around the string are optional. DynamicVariables=1 IS required.

The plugin will return 1 (the Explorer window was found) or -1 (the Explorer window was not found)

Code: Select all

[Rainmeter]
Update=1000
DynamicWindowSize=1
AccurateText=1

[Metadata]
Name=ExplorerWindow
Author=JSMorley
Information=Description:|Demonstrates the ExplorerWindow plugin
Version=Feb 17, 2018
License=Creative Commons Attribution-Non-Commercial-Share Alike 3.0

[Variables]
Folder1=Test Folder
Folder2=Another Test Folder

[MeasureTitle]
Measure=Plugin
Plugin=ExplorerWindow
Disabled=1

[MeasureCheckFolders]
Measure=Calc
IfCondition=[&MeasureTitle:FindIt([#Folder1])] = 1
IfTrueAction=[!SetOption MeterOpenFolder1 FontColor "0,237,27,255"][!UpdateMeter MeterOpenFolder1][!Redraw]
IfFalseAction=[!SetOption MeterOpenFolder1 FontColor "180,180,180,255"][!UpdateMeter MeterOpenFolder1][!Redraw]
IfCondition2=[&MeasureTitle:FindIt([#Folder2])] = 1
IfTrueAction2=[!SetOption MeterOpenFolder2 FontColor "0,237,27,255"][!UpdateMeter MeterOpenFolder2][!Redraw]
IfFalseAction2=[!SetOption MeterOpenFolder2 FontColor "180,180,180,255"][!UpdateMeter MeterOpenFolder2][!Redraw]
DynamicVariables=1

[MeterOpenFolder1]
Meter=String
FontSize=14
FontWeight=400
FontColor=255,255,255,255
SolidColor=47,47,47,255
Padding=5,5,5,5
AntiAlias=1
Text=Open #Folder1#
LeftMouseUpAction=["#@##Folder1#"]

[MeterOpenFolder2]
Meter=String
Y=5R
FontSize=14
FontWeight=400
FontColor=255,255,255,255
SolidColor=47,47,47,255
Padding=5,5,5,5
AntiAlias=1
Text=Open #Folder2#
LeftMouseUpAction=["#@##Folder2#"]
1.jpg
Plugin C++ source code:

Code: Select all

#include <Windows.h>
#include "../../API/RainmeterAPI.h"
#include <string>

struct Measure
{
	Measure() {}
};

PLUGIN_EXPORT void Initialize(void** data, void* rm)
{
	Measure* measure = new Measure;
	*data = measure;
}

PLUGIN_EXPORT void Reload(void* data, void* rm, double* maxValue)
{
	Measure* measure = (Measure*)data;
}

PLUGIN_EXPORT double Update(void* data)
{
	Measure* measure = (Measure*)data;
	return 0, 0;
}

//PLUGIN_EXPORT LPCWSTR GetString(void* data)
//{
//    Measure* measure = (Measure*)data;
//    return  L"";
//}

PLUGIN_EXPORT LPCWSTR FindIt(void* data, const int argc, const LPCWSTR* argv)
{
	Measure* measure = (Measure*)data;

	// no args
	if (argc == 0) return L"0";

	std::wstring str = argv[0];
	if (str[0] == L'"')
	{
		str.erase(0, 1);
	}

	if (str[str.size() - 1] == L'"')
	{
		str.erase(str.size() - 1);
	}

	if (FindWindow(L"CabinetWClass", str.c_str())) {
		return L"1";
	}
	return L"-1";
}

PLUGIN_EXPORT void Finalize(void* data)
{
	Measure* measure = (Measure*)data;
	delete measure;
}
And here are the 32bit and 64bit plugin files for distribution:
ExplorerWindow.zip
(85.05 KiB) Downloaded 28 times
Do keep in mind that by default the "Title" of an explorer window is the name of the specific folder you are in, not the entire path. That can be changed, in Folder Options.
User avatar
StArL0rd84
Posts: 424
Joined: February 8th, 2015, 10:07 pm
Location: EU, Denmark.

Re: Help with reverse engineering a skin

Post by StArL0rd84 »

Oh wow. Thank you so much Jsmorley!
Now you will hopefully not hear any more wining from me on this subject ;-)
I just felt like if apps had the Process plugin, something equivalent should exist for folders too.
I'm glad it was possible after all.
Thanks again for taking the time to make it.
User avatar
jsmorley
Developer
Posts: 22628
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Help with reverse engineering a skin

Post by jsmorley »

StArL0rd84 wrote:Oh wow. Thank you so much Jsmorley!
Now you will hopefully not hear any more wining from me on this subject ;-)
I just felt like if apps had the Process plugin, something equivalent should exist for folders too.
I'm glad it was possible after all.
Thanks again for taking the time to make it.
Glad to help.

Again, remember that by default Explorer does not display / set the entire "path" in the Title of the Explorer window, but just the specific single folder name. That is fine, but does mean that

C:\Test1\FolderName
C:\Test2\FolderName

Would both return or "1" (true) when the plugin searches for "FolderName". This possibility for ambiguity is a bit of a shortfall.

If however, you go into the "Folder Options" in Windows, and change the default setting:
2.jpg
Then the unambiguous full "path" to the folder is used, and this skin:

Code: Select all

[Rainmeter]
Update=1000
DynamicWindowSize=1
AccurateText=1

[Metadata]
Name=ExplorerWindow
Author=JSMorley
Information=Description:|Demonstrates the ExplorerWindow plugin
Version=Feb 17, 2018
License=Creative Commons Attribution-Non-Commercial-Share Alike 3.0

[Variables]
Folder1=Test Folder
Folder2=Another Test Folder

[MeasureTitle]
Measure=Plugin
Plugin=ExplorerWindow
Disabled=1

[MeasureCheckFolders]
Measure=Calc
IfCondition=[&MeasureTitle:FindIt([#@][#Folder1])] = 1
IfTrueAction=[!SetOption MeterOpenFolder1 FontColor "0,237,27,255"][!UpdateMeter MeterOpenFolder1][!Redraw]
IfFalseAction=[!SetOption MeterOpenFolder1 FontColor "180,180,180,255"][!UpdateMeter MeterOpenFolder1][!Redraw]
IfCondition2=[&MeasureTitle:FindIt([#@][#Folder2])] = 1
IfTrueAction2=[!SetOption MeterOpenFolder2 FontColor "0,237,27,255"][!UpdateMeter MeterOpenFolder2][!Redraw]
IfFalseAction2=[!SetOption MeterOpenFolder2 FontColor "180,180,180,255"][!UpdateMeter MeterOpenFolder2][!Redraw]
DynamicVariables=1

[MeterOpenFolder1]
Meter=String
FontSize=14
FontWeight=400
FontColor=255,255,255,255
SolidColor=47,47,47,255
Padding=5,5,5,5
AntiAlias=1
Text=Open #Folder1#
LeftMouseUpAction=["#@##Folder1#"]

[MeterOpenFolder2]
Meter=String
Y=5R
FontSize=14
FontWeight=400
FontColor=255,255,255,255
SolidColor=47,47,47,255
Padding=5,5,5,5
AntiAlias=1
Text=Open #Folder2#
LeftMouseUpAction=["#@##Folder2#"]
1.jpg
Would be more reliable. The rub is, that this is a Windows setting, and not something that any skin author should try to "force" on anyone's computer. That would be heavy-handed in the extreme.

All in all, it will be difficult to distribute skins that use this, as what you would have to do is search the registry to see if that folder option is set or not on the skin user's system, and adjust how you call the folder name (name or full path and name) to the plugin. You are going to have to make a judgment call as to the cost / benefit analysis of this.

I believe the registry key is:

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\CabinetState\FullPathAddress

And that key may not exist if the default has never been changed. Still, the lack of the key, or a value of "0" tells you one things, and a value of "1" tells you the other. You HAVE to get it "right", as if they have it set and you look for just the folder name it will fail, and if they have the default and you look for the full path it will fail. Do or do not, there is no try...
User avatar
jsmorley
Developer
Posts: 22628
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Help with reverse engineering a skin

Post by jsmorley »

It occurs to me that you could just look for "either or" of the two forms...

Code: Select all

[MeasureCheckFolders]
Measure=Calc
IfCondition=([&MeasureTitle:FindIt([#@][#Folder1])] = 1) || ([&MeasureTitle:FindIt([#Folder1])] = 1)
IfTrueAction=[!SetOption MeterOpenFolder1 FontColor "0,237,27,255"][!UpdateMeter MeterOpenFolder1][!Redraw]
IfFalseAction=[!SetOption MeterOpenFolder1 FontColor "180,180,180,255"][!UpdateMeter MeterOpenFolder1][!Redraw]
IfCondition2=([&MeasureTitle:FindIt([#@][#Folder2])] = 1) || ([&MeasureTitle:FindIt([#Folder2])] = 1)
IfTrueAction2=[!SetOption MeterOpenFolder2 FontColor "0,237,27,255"][!UpdateMeter MeterOpenFolder2][!Redraw]
IfFalseAction2=[!SetOption MeterOpenFolder2 FontColor "180,180,180,255"][!UpdateMeter MeterOpenFolder2][!Redraw]
DynamicVariables=1
That eliminates searching the registry and altering what you look for, and although it does double the number of "hits" to the function inside the plugin, the amount of work the plugin does is trivial.
User avatar
jsmorley
Developer
Posts: 22628
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Help with reverse engineering a skin

Post by jsmorley »

There are some things that look like folders that really aren't, and have to be massaged a bit, and other "gotchas"...

Code: Select all

[Rainmeter]
Update=1000
DynamicWindowSize=1
AccurateText=1

[Metadata]
Name=ExplorerWindow
Author=JSMorley
Information=Description:|Demonstrates the ExplorerWindow plugin
Version=Feb 17, 2018
License=Creative Commons Attribution-Non-Commercial-Share Alike 3.0

[Variables]
Folder1=This PC
Folder2=Documents
Folder3=Music
Folder4=Network
Folder5=Rainmeter Skins

[SKINSPATHnoSlash]
Measure=String
String=#SKINSPATH#
RegExpSubstitute=1
Substitute="(?siU)(.*)\\$":"\1"
UpdateDivider=-1

[MeasureTitle]
Measure=Plugin
Plugin=ExplorerWindow
Disabled=1

[MeasureCheckFolders]
Measure=Calc
IfCondition=[&MeasureTitle:FindIt([#Folder1])] = 1
IfTrueAction=[!SetOption MeterOpenFolder1 FontColor "0,237,27,255"][!UpdateMeter MeterOpenFolder1][!Redraw]
IfFalseAction=[!SetOption MeterOpenFolder1 FontColor "180,180,180,255"][!UpdateMeter MeterOpenFolder1][!Redraw]
IfCondition2=([&MeasureTitle:FindIt(%USERPROFILE%\[#Folder2])] = 1) || ([&MeasureTitle:FindIt([#Folder2])] = 1)
IfTrueAction2=[!SetOption MeterOpenFolder2 FontColor "0,237,27,255"][!UpdateMeter MeterOpenFolder2][!Redraw]
IfFalseAction2=[!SetOption MeterOpenFolder2 FontColor "180,180,180,255"][!UpdateMeter MeterOpenFolder2][!Redraw]
IfCondition3=([&MeasureTitle:FindIt(%USERPROFILE%\[#Folder3])] = 1) || ([&MeasureTitle:FindIt([#Folder3])] = 1)
IfTrueAction3=[!SetOption MeterOpenFolder3 FontColor "0,237,27,255"][!UpdateMeter MeterOpenFolder3][!Redraw]
IfFalseAction3=[!SetOption MeterOpenFolder3 FontColor "180,180,180,255"][!UpdateMeter MeterOpenFolder3][!Redraw]
IfCondition4=[&MeasureTitle:FindIt([#Folder4])] = 1
IfTrueAction4=[!SetOption MeterOpenFolder4 FontColor "0,237,27,255"][!UpdateMeter MeterOpenFolder4][!Redraw]
IfFalseAction4=[!SetOption MeterOpenFolder4 FontColor "180,180,180,255"][!UpdateMeter MeterOpenFolder4][!Redraw]
IfCondition5=([&MeasureTitle:FindIt([&SKINSPATHnoSlash])] = 1) || ([&MeasureTitle:FindIt(Skins)] = 1)
IfTrueAction5=[!SetOption MeterOpenFolder5 FontColor "0,237,27,255"][!UpdateMeter MeterOpenFolder5][!Redraw]
IfFalseAction5=[!SetOption MeterOpenFolder5 FontColor "180,180,180,255"][!UpdateMeter MeterOpenFolder5][!Redraw]
DynamicVariables=1

[MeterOpenFolder1]
Meter=String
W=140
FontSize=14
FontWeight=400
FontColor=255,255,255,255
SolidColor=47,47,47,255
Padding=5,5,5,5
AntiAlias=1
Text=#Folder1#
LeftMouseUpAction=["Explorer" /select,This PC]

[MeterOpenFolder2]
Meter=String
W=140
Y=0R
FontSize=14
FontWeight=400
FontColor=255,255,255,255
SolidColor=47,47,47,255
Padding=5,5,5,5
AntiAlias=1
Text=#Folder2#
LeftMouseUpAction=["%USERPROFILE%\#Folder2#"]

[MeterOpenFolder3]
Meter=String
W=140
Y=0R
FontSize=14
FontWeight=400
FontColor=255,255,255,255
SolidColor=47,47,47,255
Padding=5,5,5,5
AntiAlias=1
Text=#Folder3#
LeftMouseUpAction=["%USERPROFILE%\#Folder3#"]

[MeterOpenFolder4]
Meter=String
W=140
Y=0R
FontSize=14
FontWeight=400
FontColor=255,255,255,255
SolidColor=47,47,47,255
Padding=5,5,5,5
AntiAlias=1
Text=#Folder4#
LeftMouseUpAction=[Shell:::{F02C1A0D-BE21-4350-88B0-7367FC96EF3C}]

[MeterOpenFolder5]
Meter=String
W=140
Y=0R
FontSize=14
FontWeight=400
FontColor=255,255,255,255
SolidColor=47,47,47,255
Padding=5,5,5,5
AntiAlias=1
Text=#Folder5#
LeftMouseUpAction=["#SKINSPATH#"]
1.jpg
So let's look at these..

1) This PC : This is not actually a folder, and you open it with a direct call to explorer.exe as you can see, but it will still work with the plugin, although the Title will always just be "This PC". There just is no "path" to it.

2) Documents : This will open, and have a Title, one of two ways. Either it will be the full path to %USERPROFILE%\Documents, and display either that full path or just "Documents", or it will open as This PC > Documents and in that case will always just be "Documents".

3) Music : This is the same as "Documents" and will open, and have a Title, one of two ways. Either it will be the full path to %USERPROFILE%\Music, and display either that full path or just "Music", or it will open as This PC > Music and in that case will always just be "Music".

4) Network : This is not a folder at all, but can be opened in an Explorer window as it it were one. It is opened with a Shell:::{CLSID} command, and will always have the Title of "Network". There just is no "path" to it. There are a boatload of other "special folders" in Windows, like "Printers" that will work the same way. Windows Special Folders.

5) Rainmeter Skins : The best, and really only way to get the full path to this is to use the #SKINSPATH# variable in Rainmeter. However, that variable ends with a trailing \ (slash), and that will never be in the Title of the window, no matter which form the Folder Options are set to. So you have to use a RegExpSubstitute / Substitute to strip off that trailing slash before you use it.

In addition, be aware that this plugin can only look for the exact folder you define. If you open Skins and then a sub-folder of Skins, that doesn't mean that Skins is still open. Doesn't work that way. While the plugin could be altered to do some form of regular expression search on the Title to support this, that would ONLY work if the system Folder Options were set to display the full path, and as we have noted, you can know that, but you can't change it. Probably 90% of users will never change that option in Folder Options. They, and in fact I, won't want to in order to support this, as it screws up the display of the icons on the Taskbar. I won't want the full path there, but it would be, it also uses the "Title". If I'm working on a bunch of skins, it's not helpful to have a bunch of icons on the Taskbar that are all truncated to "C:\Users\Jeffrey\Doc...". No sir, don't like it a bit. I never, and won't, set that option, it's pointless, ugly and redundant. The full path is already in the "breadcrumb navigaton" under the Title Bar.

Anyway, this example skin is just to work out some of the kinks you might run into. There are probably others you will hit upon...

Guess what I'm getting at is that if you distribute a skin, and allow the users to set their own "folders" to open and watch, these are the kinds of traps they are going to fall into. In addition, this is all based on how Windows 10 works, and I don't know, and don't give a tinker's damn, what differences there might be with Windows 7.
Post Reply