It is currently December 3rd, 2021, 6:55 am

Focus Plugin

Share and get help with Plugins and Addons
User avatar
death.crafter
Rainmeter Sage
Posts: 1205
Joined: April 24th, 2021, 8:13 pm

Focus Plugin

Post by death.crafter »

A Rainmeter plugin to bring skins to focus.

⚠️⚠️⚠️⚠️⚠️
Please do not use if not absolutely necessary. Quoting Brian, "Window focus should almost always lie with the user."
⚠️⚠️⚠️⚠️⚠️

Usage:
Measure:

Code: Select all

[MeasureName]
Measure=Plugin
Plugin=Focus
FocusOnRefresh=0
Options:

Code: Select all

FocusOnRefresh : brings focus to the current config on refresh
- 0(default)
- 1
Return value:
0 : if current config is not in focus
1 : if current config is in focus
Commands:

Code: Select all

[!CommandMeasure MeasureName "config"]
Example: [!CommandMeasure Focus "JSMeter\System"]
Example:
Code:

Code: Select all

[Rainmeter]
Update=1000
AccurateText=1
OnFocusAction=[!SetOption Image SolidColor 00BBFF][!UpdateMeter Image][!Redraw]
OnUnfocusAction=[!SetOption Image SolidColor 00FF00][!UpdateMeter Image][!Redraw]

[Focus]
Measure=Plugin
Plugin=Focus
FocusOnRefresh=0

[Image]
Meter=Image
H=100
W=200
SolidColor=FF00FF
MouseOverAction=[!CommandMeasure Focus "[#CURRENTCONFIG]"]
Example skin:
FocusPluginExample_1.0.0.1.rmskin
Plugin:
Zip:
Focus_1.0.0.1.zip
Installer:
FocusPluginExample_1.0.0.1.rmskin
Cautions:
Do not use like:

Code: Select all

OnRefreshAction=[!CommandMeasure MeasureName "config1"][!CommandMeasure MeasureName "config2"]
or

Code: Select all

FocusOnRefresh=1
;and
OnRefreshAction=[!CommandMeasure MeasureName "other config"]
Source code(C++):

Code: Select all

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

struct Measure
{
	HWND windowHandle;

	int focusOnRefresh;
	Measure() : windowHandle(NULL), focusOnRefresh()
	{
	};
};

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

	measure->windowHandle = RmGetSkinWindow(rm);

	measure->focusOnRefresh = RmReadInt(rm, L"FocusOnRefresh", 0);

	if (measure->focusOnRefresh == 1) {
		while (measure->windowHandle != GetForegroundWindow()) {
			SetForegroundWindow(measure->windowHandle);
		}
	}
}

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

PLUGIN_EXPORT double Update(void* data)
{
	Measure* measure = (Measure*)data;

	if (measure->windowHandle != GetForegroundWindow()) {
		return 0.0;
	} else {
		return 1.0;
	}
}

HWND GetSkinWindow(const wchar_t* configName)
{
	HWND trayWnd = FindWindow(L"RainmeterTrayClass", NULL);
	if (trayWnd)
	{
		COPYDATASTRUCT cds;
		cds.dwData = 5101;
		cds.cbData = (DWORD)(wcslen(configName) + 1) * sizeof(wchar_t);
		cds.lpData = (void*)configName;
		return (HWND)SendMessage(trayWnd, WM_COPYDATA, 0, (LPARAM)&cds);
	}

	return NULL;
}

PLUGIN_EXPORT void ExecuteBang(void* data, LPCWSTR args)
{
	Measure* measure = (Measure*)data;
	HWND hwnd = GetSkinWindow(args);
	if (!hwnd) {
		RmLog(LOG_ERROR, L"Focus.dll: Invalid config. Make sure config is loaded!");
	}
	else {
		while (hwnd != GetForegroundWindow()) {
			SetForegroundWindow(hwnd);
		}
	}
}

PLUGIN_EXPORT void Finalize(void* data)
{
	Measure* measure = (Measure*)data;
	delete measure;
}
And this is my first plugin. So please be kind and tell me if I am doing something wrong.
You do not have the required permissions to view the files attached to this post.
from the Realm of Death
User avatar
Yincognito
Rainmeter Sage
Posts: 4108
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Focus Plugin

Post by Yincognito »

Didn't try it yet, but well done. :thumbup:
Two things though:
- you should explain what effect will have doing any of the things you cautioned against (e.g. crash, other side effect, no effect at all other that the thing being illogical, etc)
- you should try to eliminate the need for these things to be cautioned against, if possible, from your code (e.g. some check against or some ignore approach if any of those situations happen), since most users will expect the plugin to "just work" irrespective of what they're trying to do (and if not, simply display a log error or notice)
User avatar
death.crafter
Rainmeter Sage
Posts: 1205
Joined: April 24th, 2021, 8:13 pm

Re: Focus Plugin

Post by death.crafter »

Yincognito wrote: July 25th, 2021, 11:58 am Didn't try it yet, but well done. :thumbup:
Two things though:
- you should explain what effect will have doing any of the things you cautioned against (e.g. crash, other side effect, no effect at all other that the thing being illogical, etc)
- you should try to eliminate the need for these things to be cautioned against, if possible, from your code (e.g. some check against or some ignore approach if any of those situations happen), since most users will expect the plugin to "just work" irrespective of what they're trying to do (and if not, simply display a log error or notice)
It wouldn't crash. It would just focus on the second config right away. You wouldn't notice when the first one was focused(it would be focused). Same for more bangs. If you use delay, you can notice the focus shifting.
It should have been an notice instead. But I don't want it used like this, that's all. One can make a loop out of these and make life hard for the user.
And similar for FocusOnRefresh=1 and OnRefreshAction=[!CommandMeasure MeasureName "other config"]. Other config will be focused right away, leaving FocusOnRefresh=1 useless.
from the Realm of Death
User avatar
Yincognito
Rainmeter Sage
Posts: 4108
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Focus Plugin

Post by Yincognito »

death.crafter wrote: July 25th, 2021, 4:01 pm It wouldn't crash. It would just focus on the second config right away. You wouldn't notice when the first one was focused(it would be focused). Same for more bangs. If you use delay, you can notice the focus shifting.
It should have been an notice instead. But I don't want it used like this, that's all. One can make a loop out of these and make life hard for the user.
And similar for FocusOnRefresh=1 and OnRefreshAction=[!CommandMeasure MeasureName "other config"]. Other config will be focused right away, leaving FocusOnRefresh=1 useless.
Ah, well, then that's ok. No need for code updates, since it's already handling these the same way everything else in Rainmeter works. I thought it was more serious, hence my previous reply. ;-)