It is currently March 28th, 2024, 10:49 pm

Getting window handle of skin

Get help with creating, editing & fixing problems with skins
User avatar
death.crafter
Rainmeter Sage
Posts: 1399
Joined: April 24th, 2021, 8:13 pm

Getting window handle of skin

Post by death.crafter »

I needed the window handle of a skin to use in a script file. I was lurking in the developer section of docs and noticed that there is an api function that returns window handle of the current skin.

So is it possible to get the window handle of a skin natively?

Thanks in advance.
P.S. I am a pure noob in C++. So, if I were to make a plugin, I would need a full descriptive guide.
from the Realm of Death
Judian81
Posts: 180
Joined: May 6th, 2021, 2:57 pm

Re: Getting window handle of skin

Post by Judian81 »

hey hello,

i do not know why you want to know the handle. but i programmed something. feel free to be open about it.

this is writen in c++ and the type is console app.

Code: Select all

//all #includes have lots to offer. but sometime needed for just one thing

//used for the function findwindowa
//#include "winuser.h"
//this is to make use of the console. you can send text to it and lots of more things
#include <iostream>
//using string without this will not work
#include <string>
//now we could use handle's
#include "windows.h"
//this is so you do not need to write std::cout and so you can just write cout
using namespace std;

// HWND FindWindow(LPCSTR lpClassName, LPCSTR lpWindowName);

int main()
{
    //send hello world! to the console window, here you see how std:: is used. but do not need it anymore because of the namespace.
    std::cout << "Hello World!\n";
    //make a string in memory that can posses 100 chars max
    char buff[100];
    //give this string the name you want
    string name = "stackoverflow";
    //save to buff, add text and %s to set name
    sprintf_s(buff, "name is: %s", name.c_str());
    //write the buff to the console
    cout << "\n";
    cout << "\n";
    cout << buff;
    //get the handle of the console
    HANDLE hwnd = GetConsoleWindow();
    cout << "\n";
    cout << "\n";
    cout << "The handle for the console: ";
    cout << hwnd;
    cout << "\n";
    cout << "\n";
    HWND hWnds = FindWindow(NULL, TEXT("Calculator"));
    cout << "The handle for Calculator application: ";
    cout << hWnds;
    cout << "\n";
    cout << "if handle is 00000000 then startup calc.exe and try again.";
    cout << "\n";
    cout << "program ended.";
    cout << "\n";
    cout << "\n";
}
that was all the code i needed to write the program. you can find the program on my github.
https://github.com/Judian81/c-console-app you have to compile it yourself.
Last edited by Judian81 on July 23rd, 2021, 2:26 am, edited 1 time in total.
Judian81
Posts: 180
Joined: May 6th, 2021, 2:57 pm

Re: Getting window handle of skin

Post by Judian81 »

ow another advice is you can use spy++ in visual studio 2019.
just go to menu->tools->spy++
User avatar
jsmorley
Developer
Posts: 22628
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Getting window handle of skin

Post by jsmorley »

death.crafter,

At the bottom of this page are examples of how to do just that in both C++ and AutoIt.

https://docs.rainmeter.net/developers/

I think I have some time tomorrow, I'll try to knock out a quick plugin for you...

You will pass it a full config name, and it will return the window handle.
User avatar
death.crafter
Rainmeter Sage
Posts: 1399
Joined: April 24th, 2021, 8:13 pm

Re: Getting window handle of skin

Post by death.crafter »

jsmorley wrote: July 23rd, 2021, 2:16 am death.crafter,

At the bottom of this page are examples of how to do just that in both C++ and AutoIt.

https://docs.rainmeter.net/developers/

I think I have some time tomorrow, I'll try to knock out a quick plugin for you...

You will pass it a full config name, and it will return the window handle.
Thanks a lot. This is what I was talking about. But I have no experience, or knowledge in building dll files. I am new to C++ and all I have done is simple console applications.

Thanks again.

P.S. if you do, please attach a source file. I want to see how things work in a Rainmeter plugin.😄
from the Realm of Death
User avatar
death.crafter
Rainmeter Sage
Posts: 1399
Joined: April 24th, 2021, 8:13 pm

Re: Getting window handle of skin

Post by death.crafter »

jsmorley wrote: July 23rd, 2021, 2:16 am death.crafter,

At the bottom of this page are examples of how to do just that in both C++ and AutoIt.

https://docs.rainmeter.net/developers/

I think I have some time tomorrow, I'll try to knock out a quick plugin for you...

You will pass it a full config name, and it will return the window handle.
I made a plugin to bring a skin to the focus. Now I need help with:

How to declare a custom function in an dll that I can call from the skin?

I mean like,

Code: Select all

SomeAction=[!CommandMeasure Focus "Focus" "config\path"]
will focus the skin in parameter.
Last edited by death.crafter on July 23rd, 2021, 8:27 am, edited 1 time in total.
from the Realm of Death
User avatar
death.crafter
Rainmeter Sage
Posts: 1399
Joined: April 24th, 2021, 8:13 pm

Re: Getting window handle of skin

Post by death.crafter »

Here is the code btw:

This is a trial code, so it just focuses the skin from the beginning.

Code: Select all

[Spoiler]#include <Windows.h>
#include <stdio.h>
#include "../../API/RainmeterAPI.h"

struct Measure
{
	HWND windowHandle;
	Measure() : windowHandle(NULL)
	{
	};
};

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

	measure->windowHandle = RmGetSkinWindow(rm);

	SetActiveWindow(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;

	HWND isActive = GetActiveWindow();

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


PLUGIN_EXPORT void Finalize(void* data)
{
	Measure* measure = (Measure*)data;
	delete measure;
}[/Spoiler]
And the plugin:
Focus.zip
You do not have the required permissions to view the files attached to this post.
from the Realm of Death
User avatar
death.crafter
Rainmeter Sage
Posts: 1399
Joined: April 24th, 2021, 8:13 pm

Re: Getting window handle of skin

Post by death.crafter »

Okay so I figured out how to use !CommandMeasure. I need help with another thing:

Code: Select all

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

	return NULL;
}

PLUGIN_EXPORT double ExecuteBang(void* data, LPCWSTR args)
{
	Measure* measure = (Measure*)data;

	std::wstring wholeBang = args;

	size_t pos = wholeBang.find(' ');

	if (pos != -1) {
		std::wstring bang = wholeBang.substr(0, pos);
		wholeBang.erase(0, pos + 1);

		if (bang == L"Focus") {
			
			HWND hwnd = GetSkinWindow(wholeBang.c_str());
			if (hwnd == NULL) {
				RmLog(LOG_ERROR, wholeBang.c_str());
				RmLog(LOG_ERROR, L"Focus.dll: Please provide valid config!");
				return 0.0;
			}
			else {
				SetActiveWindow(hwnd);
				return 1.0;
			}
		}
		else {
			RmLog(LOG_ERROR, L"Focus.dll: Command invalid!");
			return 0.0;
		}
	}
	else if (wholeBang == L"Focus") {
		SetActiveWindow(measure->windowHandle);
		return 1.0;
	}
	else {
		RmLog(LOG_ERROR, L"Focus.dll: Command invalid!");
		return 0.0;
	}
}
So [!CommandMeasure Focus "Focus"] works.

But when [!CommandMeasure Focus "Focus configName"] is used, GetSkinWindow() function returns null no matter the config.

I also tried to take LPCWSTR configName, as the parameter of GetSkinWindow but same results.
from the Realm of Death
User avatar
jsmorley
Developer
Posts: 22628
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Getting window handle of skin

Post by jsmorley »

death.crafter wrote: July 23rd, 2021, 12:21 pm Okay so I figured out how to use !CommandMeasure. I need help with another thing:

Code: Select all

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

	return NULL;
}

PLUGIN_EXPORT double ExecuteBang(void* data, LPCWSTR args)
{
	Measure* measure = (Measure*)data;

	std::wstring wholeBang = args;

	size_t pos = wholeBang.find(' ');

	if (pos != -1) {
		std::wstring bang = wholeBang.substr(0, pos);
		wholeBang.erase(0, pos + 1);

		if (bang == L"Focus") {
			
			HWND hwnd = GetSkinWindow(wholeBang.c_str());
			if (hwnd == NULL) {
				RmLog(LOG_ERROR, wholeBang.c_str());
				RmLog(LOG_ERROR, L"Focus.dll: Please provide valid config!");
				return 0.0;
			}
			else {
				SetActiveWindow(hwnd);
				return 1.0;
			}
		}
		else {
			RmLog(LOG_ERROR, L"Focus.dll: Command invalid!");
			return 0.0;
		}
	}
	else if (wholeBang == L"Focus") {
		SetActiveWindow(measure->windowHandle);
		return 1.0;
	}
	else {
		RmLog(LOG_ERROR, L"Focus.dll: Command invalid!");
		return 0.0;
	}
}
So [!CommandMeasure Focus "Focus"] works.

But when [!CommandMeasure Focus "Focus configName"] is used, GetSkinWindow() function returns null no matter the config.

I also tried to take LPCWSTR configName, as the parameter of GetSkinWindow but same results.
In this code, you need to break up "Focus" and "ConfigName" into two separate arguments. Although I'm not sure I see the need for the "Focus" argument. Isn't giving focus to a skin based on ConfigName the entire point of the plugin?
User avatar
death.crafter
Rainmeter Sage
Posts: 1399
Joined: April 24th, 2021, 8:13 pm

Re: Getting window handle of skin

Post by death.crafter »

jsmorley wrote: July 23rd, 2021, 1:30 pm In this code, you need to break up "Focus" and "ConfigName" into two separate arguments. Although I'm not sure I see the need for the "Focus" argument. Isn't giving focus to a skin based on ConfigName the entire point of the plugin?
I didn't think of this. Thanks for pointing out. Lemme try that out.
from the Realm of Death