WinToast icon indicating copy to clipboard operation
WinToast copied to clipboard

Click event is not fired from Action Center

Open malja opened this issue 6 years ago • 10 comments

Hi all,

I'm using following code (basically simplified WinToast example) to create a notification with attached event handler and one action:

#include "wintoastlib.h"
#include <string>

using namespace WinToastLib;

class CustomHandler : public IWinToastHandler {
public:
	void toastActivated() const {
		std::wcout << L"The user clicked in this toast" << std::endl;
	}

	void toastActivated(int actionIndex) const {
		std::wcout << L"The user clicked on action #" << actionIndex << std::endl;
	}

	void toastDismissed(WinToastDismissalReason state) const {
		switch (state) {
		case UserCanceled:
			std::wcout << L"The user dismissed this toast" << std::endl;
			break;
		case TimedOut:
			std::wcout << L"The toast has timed out" << std::endl;
			break;
		case ApplicationHidden:
			std::wcout << L"The application hid the toast using ToastNotifier.hide()" << std::endl;
			break;
		default:
			std::wcout << L"Toast not activated" << std::endl;
			break;
		}
	}

	void toastFailed() const {
		std::wcout << L"Error showing current toast" << std::endl;
	}
};

int main() {

	std::wstring appName = L"Console WinToast Example",
		appUserModelID = L"WinToast Console Example",
		text = L"Test";

	WinToast::instance()->setAppName(appName);
	WinToast::instance()->setAppUserModelId(appUserModelID);

	if (!WinToast::instance()->initialize()) {
		std::wcerr << L"Error, your system in not compatible!" << std::endl;
		return -1;
	}

	WinToastTemplate templ(WinToastTemplate::Text01);
	templ.setTextField(text, WinToastTemplate::FirstLine);
	templ.addAction(L"Action");
	templ.setDuration(WinToastTemplate::Duration::Short);

	WinToast::instance()->showToast(templ, new CustomHandler());

	Sleep(15000);

	return 0;
}

The problem is, when notification is moved to Action Center (after short duration expires), either toastActivated(void) nor the toastActivated(int) method of CustomHandler is called.

Is something wrong with the code, or is this normal and intended behavior? If so, I need to get them working from Action Center, is there a way?

Thank you.

malja avatar Apr 30 '18 21:04 malja

I'm not sure, but I think that the App User Model ID is not a valid one, the expect format is the one that you can find in this link:

CompanyName.ProductName.SubProduct.VersionInformation

There is a helper function in the class to avoid those problems. Try it and I will try to figure out a way to reproduce the problem.

mohabouje avatar May 02 '18 08:05 mohabouje

Yes, you are rigth, I changed it to:

std::wstring appName = L"test";
std::wstring text = L"Notification test";

WinToast::instance()->setAppName(appName);
WinToast::instance()->setAppUserModelId(
    WinToast::instance()->configureAUMI(L"company", L"product", L"subproduct", L"version")
);

But the issue persist. To reproduce it, follow those steps:

  1. Run compiled code posted in the first comment (with changes above)
  2. Wait until notification moves to Action Center
  3. Open Action Center
  4. Try to click on notification or on action button.

In my case, the last event I see in console is "Toast has timed out". Method toastActivated() is not called at all.

malja avatar May 02 '18 09:05 malja

Hi @mohabouje, is there any update on this?

malja avatar May 17 '18 21:05 malja

I encountered the same issue. Once a notification message disappears and goes to Windows Action Center, click event is not triggered when clicking on the notification from Action Center.

jiakuan avatar Jun 01 '18 01:06 jiakuan

@malja @jiakuan guys, this is not implemented yet If you check the src code you will find a link with the modifications to be implemented. The library need to create a notification activator:

// The UUID CLSID must be unique to your app. Create a new GUID if copying this code.
class DECLSPEC_UUID("replaced-with-your-guid-C173E6ADF0C3") NotificationActivator WrlSealed WrlFinal
    : public RuntimeClass<RuntimeClassFlags<ClassicCom>, INotificationActivationCallback>
{
public:
    virtual HRESULT STDMETHODCALLTYPE Activate(
        _In_ LPCWSTR appUserModelId,
        _In_ LPCWSTR invokedArgs,
        _In_reads_(dataCount) const NOTIFICATION_USER_INPUT_DATA* data,
        ULONG dataCount) override
    {
        // TODO: Handle activation
    }
};

// Flag class as COM creatable
CoCreatableClass(NotificationActivator);

Then you have to register AUMID and the COM server:

// Register AUMID and COM server (for Desktop Bridge apps, this no-ops)
hr = DesktopNotificationManagerCompat::RegisterAumidAndComServer(L"YourCompany.YourApp", __uuidof(NotificationActivator));
// Register activator type
hr = DesktopNotificationManagerCompat::RegisterActivator();

All the information can be found here:

Send a local toast notification from desktop C++ WRL apps

Right now, I'm a little bit busy but I will try to do it as soon as possible. You are free to implement it by yourself and create a PR to share with the community! Any contribution is welcome!

mohabouje avatar Jun 01 '18 08:06 mohabouje

@mohabouje I am sorry for the delay. I had no time for programming lately. But yesterday I basically did step by step follow up of linked tutorial. But my Activator class is never called. As far as I know.

What works is that program is executed with -ToastActivated command line parameter. This may be one way of handling notifications. But no additional info is passed with it - the program does not know which notification did start it.

In addition, I have not found a way of defining UUID for Activator class dynamicaly on runtime. This could be problem from python binding later on.

My source code: https://github.com/malja/WinToast/tree/background/WinToast

PS: Notifications are not removed from Action Center when clicked. This should be implemented in Activator class. There is a tutorial on it. But it involves notification tags. And I wanted the code to stay as simple as possible before all bugs are fixed.

Any ideas?

malja avatar Sep 03 '18 19:09 malja

Hi -

I'll try to dig into this a bit more on my own, but do you know why I would be able to run the WinToast console demo from Visual Studio, yet not be able to run it as a standalone (or from the start menu, where the demo installs it as "yolo")? The console window flashes and then nothing happens.

Thank you.

rcohn avatar Apr 15 '19 14:04 rcohn

OK. The solution is rather simple. I was trying to execute the program without any arguments. The console flashed briefly and the program quit. Running that console app from another cmd window shows the help args listed out. Once I added command args, the app works normally.

Thanks.

rcohn avatar Apr 17 '19 14:04 rcohn

@mohabouje Any update on this?

ZhangTianrong avatar May 04 '21 08:05 ZhangTianrong

Trying to follow @malja and @rcohn changes to implement a standard way or provide some documentation for the users to implement this. I plan to make these changes part of version v1.4.0. PRs are welcome if anyone has a better approach to doing this.

Please see https://github.com/mohabouje/WinToast/issues/86 for more details.

mohabouje avatar Apr 10 '23 10:04 mohabouje