2026-03-29 13:56:50 -05:00
|
|
|
/**
|
|
|
|
|
* WinToastWrapper.h
|
|
|
|
|
*
|
|
|
|
|
* Flat C API that wraps WinToastLib (https://github.com/mohabouje/WinToast).
|
|
|
|
|
* This header is the sole interface between the managed P/Invoke layer and
|
|
|
|
|
* the C++ WinToastLib implementation.
|
|
|
|
|
*
|
|
|
|
|
* ABI contract (must stay in sync with WinToastNative.cs):
|
|
|
|
|
* - All strings are wchar_t* (UTF-16LE, null-terminated).
|
|
|
|
|
* - Callbacks are called on a WinRT thread-pool thread, NOT the calling STA thread.
|
|
|
|
|
* - WNT_ShowToast must be called from the STA thread that called WNT_Initialize.
|
|
|
|
|
* - WNT_HideToast must be called from the same STA thread.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
#include <Windows.h>
|
|
|
|
|
|
|
|
|
|
#ifdef WINTOASTWRAPPER_EXPORTS
|
|
|
|
|
#define NOTIFYAPI __declspec(dllexport)
|
|
|
|
|
#else
|
|
|
|
|
#define NOTIFYAPI __declspec(dllimport)
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
|
extern "C" {
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------
|
|
|
|
|
* Callback function pointer types
|
|
|
|
|
* ------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
/** Called when the user clicks the notification body (no button). */
|
|
|
|
|
typedef void (CALLBACK* WNT_ActivatedCallback)(INT64 toastId);
|
|
|
|
|
|
|
|
|
|
/** Called when the user clicks one of the action buttons. */
|
|
|
|
|
typedef void (CALLBACK* WNT_ButtonActivatedCallback)(INT64 toastId, int buttonIndex);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Called when the notification is dismissed.
|
|
|
|
|
* reason: 0 = UserCancelled, 1 = ApplicationHidden, 2 = TimedOut
|
|
|
|
|
*/
|
|
|
|
|
typedef void (CALLBACK* WNT_DismissedCallback)(INT64 toastId, int reason);
|
|
|
|
|
|
|
|
|
|
/** Called when the notification fails to display. */
|
|
|
|
|
typedef void (CALLBACK* WNT_FailedCallback)(INT64 toastId);
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------
|
|
|
|
|
* Structs (must match StructLayout in WinToastNative.cs exactly)
|
|
|
|
|
* ------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
typedef enum _WNT_Scenario {
|
|
|
|
|
WNT_SCENARIO_DEFAULT = 0,
|
|
|
|
|
WNT_SCENARIO_ALARM = 1,
|
|
|
|
|
WNT_SCENARIO_REMINDER = 2,
|
|
|
|
|
WNT_SCENARIO_INCOMING_CALL = 3
|
|
|
|
|
} WNT_Scenario;
|
|
|
|
|
|
|
|
|
|
typedef enum _WNT_AudioOption {
|
|
|
|
|
WNT_AUDIO_DEFAULT = 0,
|
|
|
|
|
WNT_AUDIO_SILENT = 1,
|
|
|
|
|
WNT_AUDIO_LOOP = 2
|
|
|
|
|
} WNT_AudioOption;
|
|
|
|
|
|
2026-04-03 00:17:37 -05:00
|
|
|
/**
|
|
|
|
|
* Selects which Windows system notification sound to play.
|
|
|
|
|
* WNT_AUDIO_FILE_NONE (-1) means no specific sound file override (use AudioOption behaviour).
|
|
|
|
|
* Values 0-25 map directly to WinToastTemplate::AudioSystemFile.
|
|
|
|
|
*/
|
|
|
|
|
typedef enum _WNT_AudioFile {
|
|
|
|
|
WNT_AUDIO_FILE_NONE = -1,
|
|
|
|
|
WNT_AUDIO_FILE_DEFAULT = 0,
|
|
|
|
|
WNT_AUDIO_FILE_IM = 1,
|
|
|
|
|
WNT_AUDIO_FILE_MAIL = 2,
|
|
|
|
|
WNT_AUDIO_FILE_REMINDER = 3,
|
|
|
|
|
WNT_AUDIO_FILE_SMS = 4,
|
|
|
|
|
WNT_AUDIO_FILE_ALARM = 5,
|
|
|
|
|
WNT_AUDIO_FILE_ALARM2 = 6,
|
|
|
|
|
WNT_AUDIO_FILE_ALARM3 = 7,
|
|
|
|
|
WNT_AUDIO_FILE_ALARM4 = 8,
|
|
|
|
|
WNT_AUDIO_FILE_ALARM5 = 9,
|
|
|
|
|
WNT_AUDIO_FILE_ALARM6 = 10,
|
|
|
|
|
WNT_AUDIO_FILE_ALARM7 = 11,
|
|
|
|
|
WNT_AUDIO_FILE_ALARM8 = 12,
|
|
|
|
|
WNT_AUDIO_FILE_ALARM9 = 13,
|
|
|
|
|
WNT_AUDIO_FILE_ALARM10 = 14,
|
|
|
|
|
WNT_AUDIO_FILE_CALL = 15,
|
|
|
|
|
WNT_AUDIO_FILE_CALL1 = 16,
|
|
|
|
|
WNT_AUDIO_FILE_CALL2 = 17,
|
|
|
|
|
WNT_AUDIO_FILE_CALL3 = 18,
|
|
|
|
|
WNT_AUDIO_FILE_CALL4 = 19,
|
|
|
|
|
WNT_AUDIO_FILE_CALL5 = 20,
|
|
|
|
|
WNT_AUDIO_FILE_CALL6 = 21,
|
|
|
|
|
WNT_AUDIO_FILE_CALL7 = 22,
|
|
|
|
|
WNT_AUDIO_FILE_CALL8 = 23,
|
|
|
|
|
WNT_AUDIO_FILE_CALL9 = 24,
|
|
|
|
|
WNT_AUDIO_FILE_CALL10 = 25
|
|
|
|
|
} WNT_AudioFile;
|
|
|
|
|
|
|
|
|
|
/** Controls how the app-logo image is cropped. */
|
|
|
|
|
typedef enum _WNT_CropHint {
|
|
|
|
|
WNT_CROP_HINT_SQUARE = 0,
|
|
|
|
|
WNT_CROP_HINT_CIRCLE = 1
|
|
|
|
|
} WNT_CropHint;
|
|
|
|
|
|
2026-03-29 13:56:50 -05:00
|
|
|
/**
|
|
|
|
|
* Describes the notification to display.
|
|
|
|
|
* All pointer fields may be NULL where noted.
|
|
|
|
|
* Callers must keep pointed-to memory valid for the duration of WNT_ShowToast.
|
2026-04-03 00:17:37 -05:00
|
|
|
*
|
|
|
|
|
* Field layout (x64, no explicit packing):
|
|
|
|
|
* offsets 0..39 — five pointers (title, body, imagePath, heroImagePath, buttonLabels)
|
|
|
|
|
* offset 40 — buttonCount (int, 4 bytes) + 4 bytes natural padding
|
|
|
|
|
* offset 48 — expirationMs (long long, 8 bytes)
|
|
|
|
|
* offset 56 — scenario (int, 4 bytes)
|
|
|
|
|
* offset 60 — audioOption (int, 4 bytes)
|
|
|
|
|
* offsets 64..79 — three new pointers (inlineImagePath, attributionText, customAudioPath)
|
|
|
|
|
* offset 88 — cropHint (int, 4 bytes)
|
|
|
|
|
* offset 92 — audioFile (int, 4 bytes)
|
|
|
|
|
* Total: 96 bytes
|
2026-03-29 13:56:50 -05:00
|
|
|
*/
|
|
|
|
|
typedef struct _WNT_ToastDescriptor {
|
2026-04-03 00:17:37 -05:00
|
|
|
const wchar_t* title; /* required */
|
|
|
|
|
const wchar_t* body; /* nullable */
|
|
|
|
|
const wchar_t* imagePath; /* nullable — absolute path; app logo override in generic templates */
|
|
|
|
|
const wchar_t* heroImagePath; /* nullable — absolute path; full-width banner above the notification */
|
|
|
|
|
const wchar_t** buttonLabels; /* nullable — array of buttonCount wchar_t* */
|
2026-03-29 13:56:50 -05:00
|
|
|
int buttonCount;
|
2026-04-03 00:17:37 -05:00
|
|
|
long long expirationMs; /* 0 = platform default */
|
2026-03-29 13:56:50 -05:00
|
|
|
WNT_Scenario scenario;
|
|
|
|
|
WNT_AudioOption audioOption;
|
2026-04-03 00:17:37 -05:00
|
|
|
/* Extended fields (added in v2): */
|
|
|
|
|
const wchar_t* inlineImagePath; /* nullable — image displayed inline inside the notification body */
|
|
|
|
|
const wchar_t* attributionText; /* nullable — small text shown at the bottom of the notification */
|
|
|
|
|
const wchar_t* customAudioPath; /* nullable — ms-winsoundevent: URI or ms-appx:/// path; overrides audioFile */
|
|
|
|
|
int cropHint; /* WNT_CropHint — how imagePath is cropped (Square or Circle) */
|
|
|
|
|
int audioFile; /* WNT_AudioFile — system sound to play; -1 = not overridden */
|
2026-03-29 13:56:50 -05:00
|
|
|
} WNT_ToastDescriptor;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Bundle of callback function pointers for one notification.
|
|
|
|
|
* The struct is copied by value inside WNT_ShowToast; callers need not keep it alive.
|
|
|
|
|
* Individual function pointers may be NULL to skip that event.
|
|
|
|
|
*/
|
|
|
|
|
typedef struct _WNT_Handler {
|
|
|
|
|
WNT_ActivatedCallback onActivated;
|
|
|
|
|
WNT_ButtonActivatedCallback onButtonActivated;
|
|
|
|
|
WNT_DismissedCallback onDismissed;
|
|
|
|
|
WNT_FailedCallback onFailed;
|
|
|
|
|
} WNT_Handler;
|
|
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------
|
|
|
|
|
* API functions
|
|
|
|
|
* ------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Initialises WinToastLib. Must be called once from an STA thread.
|
|
|
|
|
*
|
|
|
|
|
* @param appName Human-readable name shown in the Action Centre.
|
|
|
|
|
* @param appUserModelId AppUserModelId (AUMI). The wrapper creates a Start-Menu
|
|
|
|
|
* shortcut carrying this AUMI automatically if one does not
|
|
|
|
|
* already exist.
|
2026-04-03 00:17:37 -05:00
|
|
|
* @param appIconPath Optional absolute path to an .ico (or .exe/.dll) file whose
|
|
|
|
|
* first icon is stamped onto the Start-Menu shortcut. This is
|
|
|
|
|
* the small icon shown in the top-left corner of every toast
|
|
|
|
|
* notification from this app. Pass NULL to use the default
|
|
|
|
|
* (the host executable's icon).
|
2026-03-29 13:56:50 -05:00
|
|
|
* @return TRUE on success.
|
|
|
|
|
*/
|
2026-04-03 00:17:37 -05:00
|
|
|
NOTIFYAPI BOOL WNT_Initialize(const wchar_t* appName, const wchar_t* appUserModelId, const wchar_t* appIconPath);
|
2026-03-29 13:56:50 -05:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Releases all WinToastLib resources. Call from the same STA thread as WNT_Initialize.
|
|
|
|
|
*/
|
|
|
|
|
NOTIFYAPI void WNT_Uninitialize(void);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns TRUE if WinToast is supported on the current Windows version (requires Win 8+).
|
|
|
|
|
* Check this before calling WNT_Initialize.
|
|
|
|
|
*/
|
|
|
|
|
NOTIFYAPI BOOL WNT_IsCompatible(void);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Displays a toast notification.
|
|
|
|
|
*
|
|
|
|
|
* Must be called from the STA thread that called WNT_Initialize.
|
|
|
|
|
*
|
|
|
|
|
* @param descriptor Pointer to a WNT_ToastDescriptor (read-only during the call).
|
|
|
|
|
* @param handler Pointer to a WNT_Handler with callback function pointers.
|
|
|
|
|
* @return A positive INT64 toast ID on success, or a negative WinToastError code on failure.
|
|
|
|
|
*/
|
|
|
|
|
NOTIFYAPI INT64 WNT_ShowToast(const WNT_ToastDescriptor* descriptor, const WNT_Handler* handler);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Programmatically dismisses a previously shown toast.
|
|
|
|
|
*
|
|
|
|
|
* Must be called from the same STA thread as WNT_ShowToast.
|
|
|
|
|
*
|
|
|
|
|
* @param toastId The ID returned by WNT_ShowToast.
|
|
|
|
|
* @return TRUE if the toast was successfully hidden.
|
|
|
|
|
*/
|
|
|
|
|
NOTIFYAPI BOOL WNT_HideToast(INT64 toastId);
|
|
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
|
} /* extern "C" */
|
|
|
|
|
#endif
|